Why is assigning a value to a bit field not giving the same value back?











up vote
33
down vote

favorite
3












I saw the below code in this Quora post:



#include <stdio.h>

struct mystruct { int enabled:1; };
int main()
{
struct mystruct s;
s.enabled = 1;
if(s.enabled == 1)
printf("Is enabledn"); // --> we think this to be printed
else
printf("Is disabled !!n");
}


In both C & C++, the output of the code is unexpectedly,




Is disabled !!




Though the "sign bit" related explanation is given in that post, I am unable to understand, how is it possible that we set something and then it doesn't reflect as it is.



Can someone give a more elaborate explanation?










share|improve this question




















  • 27




    Since the bitfield is declared as int i think it only can hold the values 0 and -1.
    – Osiris
    13 hours ago






  • 3




    just think of it how int stores -1. All bits are set to 1. Hence, if you only have one bit it clearly has to be -1. So 1 and -1 in the 1 bit int are the same. Change the check to 'if (s.enabled != 0)' and it works. Because 0 it can't be.
    – Jürgen
    13 hours ago










  • It is true that these rules are the same in C and C++. But according to the tag usage policies, we should only tag this as C and refrain from cross-tagging when not needed. I'll remove the C++ part, it should not affect any posted answers.
    – Lundin
    12 hours ago






  • 3




    Have you tried changing it to struct mystruct { unsigned int enabled:1; };?
    – ChatterOne
    12 hours ago















up vote
33
down vote

favorite
3












I saw the below code in this Quora post:



#include <stdio.h>

struct mystruct { int enabled:1; };
int main()
{
struct mystruct s;
s.enabled = 1;
if(s.enabled == 1)
printf("Is enabledn"); // --> we think this to be printed
else
printf("Is disabled !!n");
}


In both C & C++, the output of the code is unexpectedly,




Is disabled !!




Though the "sign bit" related explanation is given in that post, I am unable to understand, how is it possible that we set something and then it doesn't reflect as it is.



Can someone give a more elaborate explanation?










share|improve this question




















  • 27




    Since the bitfield is declared as int i think it only can hold the values 0 and -1.
    – Osiris
    13 hours ago






  • 3




    just think of it how int stores -1. All bits are set to 1. Hence, if you only have one bit it clearly has to be -1. So 1 and -1 in the 1 bit int are the same. Change the check to 'if (s.enabled != 0)' and it works. Because 0 it can't be.
    – Jürgen
    13 hours ago










  • It is true that these rules are the same in C and C++. But according to the tag usage policies, we should only tag this as C and refrain from cross-tagging when not needed. I'll remove the C++ part, it should not affect any posted answers.
    – Lundin
    12 hours ago






  • 3




    Have you tried changing it to struct mystruct { unsigned int enabled:1; };?
    – ChatterOne
    12 hours ago













up vote
33
down vote

favorite
3









up vote
33
down vote

favorite
3






3





I saw the below code in this Quora post:



#include <stdio.h>

struct mystruct { int enabled:1; };
int main()
{
struct mystruct s;
s.enabled = 1;
if(s.enabled == 1)
printf("Is enabledn"); // --> we think this to be printed
else
printf("Is disabled !!n");
}


In both C & C++, the output of the code is unexpectedly,




Is disabled !!




Though the "sign bit" related explanation is given in that post, I am unable to understand, how is it possible that we set something and then it doesn't reflect as it is.



Can someone give a more elaborate explanation?










share|improve this question















I saw the below code in this Quora post:



#include <stdio.h>

struct mystruct { int enabled:1; };
int main()
{
struct mystruct s;
s.enabled = 1;
if(s.enabled == 1)
printf("Is enabledn"); // --> we think this to be printed
else
printf("Is disabled !!n");
}


In both C & C++, the output of the code is unexpectedly,




Is disabled !!




Though the "sign bit" related explanation is given in that post, I am unable to understand, how is it possible that we set something and then it doesn't reflect as it is.



Can someone give a more elaborate explanation?







c++ c bit-fields signed-integer implementation-defined-behavior






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 39 mins ago









Boann

36.7k1287121




36.7k1287121










asked 13 hours ago









iammilind

44k19123248




44k19123248








  • 27




    Since the bitfield is declared as int i think it only can hold the values 0 and -1.
    – Osiris
    13 hours ago






  • 3




    just think of it how int stores -1. All bits are set to 1. Hence, if you only have one bit it clearly has to be -1. So 1 and -1 in the 1 bit int are the same. Change the check to 'if (s.enabled != 0)' and it works. Because 0 it can't be.
    – Jürgen
    13 hours ago










  • It is true that these rules are the same in C and C++. But according to the tag usage policies, we should only tag this as C and refrain from cross-tagging when not needed. I'll remove the C++ part, it should not affect any posted answers.
    – Lundin
    12 hours ago






  • 3




    Have you tried changing it to struct mystruct { unsigned int enabled:1; };?
    – ChatterOne
    12 hours ago














  • 27




    Since the bitfield is declared as int i think it only can hold the values 0 and -1.
    – Osiris
    13 hours ago






  • 3




    just think of it how int stores -1. All bits are set to 1. Hence, if you only have one bit it clearly has to be -1. So 1 and -1 in the 1 bit int are the same. Change the check to 'if (s.enabled != 0)' and it works. Because 0 it can't be.
    – Jürgen
    13 hours ago










  • It is true that these rules are the same in C and C++. But according to the tag usage policies, we should only tag this as C and refrain from cross-tagging when not needed. I'll remove the C++ part, it should not affect any posted answers.
    – Lundin
    12 hours ago






  • 3




    Have you tried changing it to struct mystruct { unsigned int enabled:1; };?
    – ChatterOne
    12 hours ago








27




27




Since the bitfield is declared as int i think it only can hold the values 0 and -1.
– Osiris
13 hours ago




Since the bitfield is declared as int i think it only can hold the values 0 and -1.
– Osiris
13 hours ago




3




3




just think of it how int stores -1. All bits are set to 1. Hence, if you only have one bit it clearly has to be -1. So 1 and -1 in the 1 bit int are the same. Change the check to 'if (s.enabled != 0)' and it works. Because 0 it can't be.
– Jürgen
13 hours ago




just think of it how int stores -1. All bits are set to 1. Hence, if you only have one bit it clearly has to be -1. So 1 and -1 in the 1 bit int are the same. Change the check to 'if (s.enabled != 0)' and it works. Because 0 it can't be.
– Jürgen
13 hours ago












It is true that these rules are the same in C and C++. But according to the tag usage policies, we should only tag this as C and refrain from cross-tagging when not needed. I'll remove the C++ part, it should not affect any posted answers.
– Lundin
12 hours ago




It is true that these rules are the same in C and C++. But according to the tag usage policies, we should only tag this as C and refrain from cross-tagging when not needed. I'll remove the C++ part, it should not affect any posted answers.
– Lundin
12 hours ago




3




3




Have you tried changing it to struct mystruct { unsigned int enabled:1; };?
– ChatterOne
12 hours ago




Have you tried changing it to struct mystruct { unsigned int enabled:1; };?
– ChatterOne
12 hours ago












4 Answers
4






active

oldest

votes

















up vote
34
down vote













Bit-fields are incredibly poorly defined by the standard. Given this code struct mystruct {int enabled:1;};, then we don't know:




  • How much space this occupies - if there are padding bits/bytes and where they are located in memory.

  • Where the bit is located in memory. Not defined and also depends on endianess.

  • Whether an int:n bitfield is to be regarded as signed or unsigned.


Regarding the last part, C17 6.7.2.1/10 says:




A bit-field is interpreted as having a signed or unsigned integer type consisting of the
specified number of bits 125)




Non-normative note explaining the above:




125) As specified in 6.7.2 above, if the actual type specifier used is int or a typedef-name defined as int,
then it is implementation-defined whether the bit-field is signed or unsigned.




In case the bitfield is to be regarded as signed int and you make a bit of size 1, then there is no room for data, only for the sign bit. This is the reason why your program might give weird results on some compilers.



Good practice:




  • Never use bit-fields for any purpose.

  • Avoid using signed int type for any form of bit manipulation.






share|improve this answer



















  • 2




    At work we have static_asserts on the size and address of bitfields just to make sure that they are not padded. We use bitfields for hardware registers in our firmware.
    – Michael
    8 hours ago


















up vote
20
down vote














I am unable to understand, how is it possible that we set something and then it doesn't show up as it is.




Are you asking why it compiles vs. gives you an error?



Yes, it should ideally give you an error. And it does, if you use your compiler's warnings. In GCC, with -Werror -Wall -pedantic:



main.cpp: In function 'int main()':
main.cpp:7:15: error: overflow in conversion from 'int' to 'signed char:1'
changes value from '1' to '-1' [-Werror=overflow]
s.enabled = 1;
^


The reasoning for why this is left up to being implementation-defined vs. an error may have more to do with historical usages, where requiring a cast would mean breaking old code. The authors of the standard may believe warnings were enough to pick up the slack for those concerned.



To throw in some prescriptivism, I'll echo @Lundin's statement: "Never use bit-fields for any purpose." If you have the kind of good reasons to get low-level and specific about your memory layout details that would get you to thinking you needed bitfields in the first place, the other associated requirements you almost certainly have will run up against their underspecification.



(TL;DR - If you're sophisticated enough to legitimately "need" bit-fields, they're not well-defined enough to serve you.)






share|improve this answer



















  • 8




    The authors of the standard were on holidays the day the bit-field chapter was designed. So the janitor had to do it. There is no rationale about anything regarding how bit-fields are designed.
    – Lundin
    13 hours ago








  • 5




    There is no coherent technical rationale. But that leads me to conclude that there was a political rationale: to avoid making any of the existing code or implementations incorrect. But the result is that there's very little about bitfields that you can rely upon.
    – John Bollinger
    13 hours ago






  • 1




    @JohnBollinger There was definitely politics in place, that caused a lot of damage to C90. I once spoke with a member of the committee who explained the source of lots of the crap - the ISO standard could not be allowed to favour certain existing technologies. This is why we are stuck with moronic things like support for 1's complement and signed magnitude, implementation-defined signedness of char, support for bytes that aren't 8 bits etc etc. They weren't allowed to give moronic computers a market disadvantage.
    – Lundin
    13 hours ago








  • 1




    @Lundin It would be interesting to see a collection of writeups and post-mortems from people who believed tradeoffs had been made in error, and why. I wonder how much study of these "we did that last time, and it did/didn't work out" has become institutional knowledge to inform the next such case, vs. just stories in people's heads.
    – HostileFork
    12 hours ago






  • 1




    This is still listed as point no. 1 of the original principles of C in the C2x Charter: "Existing code is important, existing implementations are not." ... "no one implementation was held up as the exemplar by which to define C: It is assumed that all existing implementations must change somewhat to conform to the Standard."
    – Leushenko
    12 hours ago


















up vote
11
down vote













This is implementation defined behavior. I am making the assumption that the machines you are running this on use twos-compliment signed integers and treat int in this case as a signed integer to explain why you don't enter if true part of the if statement.



struct mystruct { int enabled:1; };


declares enable as a 1 bit bit-field. Since it is signed, the valid values are -1 and 0. Setting the field to 1 overflows that bit going back to -1 (this is undefined behavior)



Essentially when dealing with a signed bit-field the max value is 2^(bits - 1) - 1 which is 0 in this case.






share|improve this answer























  • "ince it is signed, the valid values are -1 and 0". Who said it is signed? It's not defined but implementation-defined behavior. If it is signed, then the valid values are - and +. 2's complement doesn't matter.
    – Lundin
    13 hours ago








  • 3




    @Lundin A 1 bit twos compliment number only has two possible values. If the bit is set, then since it is the sign bit, it is -1. If it isn't set then it is "positive" 0. I know this is implementation defined, I'm just explaining the results using the most common implantation
    – NathanOliver
    13 hours ago










  • The key here is rather that 2's complement or any other signed form cannot function with a single bit available.
    – Lundin
    13 hours ago






  • 1




    @JohnBollinger I understand that. That's why I have the discliamer that this is implementation defined. At least for the big 3 they all treat int as signed in this case. It is a shame that bit-fields are so under specified. It's basically here is this feature, consult your compiler on how to use it.
    – NathanOliver
    13 hours ago








  • 1




    @Lundin, the standard's wording for the representation of signed integers can perfectly well handle the case where there are zero value bits, at least in two of the three allowed alternatives. This works because it assigns (negative) place values to sign bits, rather than giving them an algorithmic interpretation.
    – John Bollinger
    13 hours ago




















up vote
3
down vote













You could think of it as that in the 2's complement system, the left-most bit is the sign bit. Any signed integer with the left-most bit set is thus a negative value.



If you have a 1-bit signed integer, it has only the sign bit. So assigning 1 to that single bit can only set the sign bit. So, when reading it back, the value is interpreted as negative and so is -1.



The values a 1 bit signed integer can hold is -2^(n-1)= -2^(1-1)= -2^0= -1 and 2^n-1= 2^1-1=0






share|improve this answer





















    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53853540%2fwhy-is-assigning-a-value-to-a-bit-field-not-giving-the-same-value-back%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    34
    down vote













    Bit-fields are incredibly poorly defined by the standard. Given this code struct mystruct {int enabled:1;};, then we don't know:




    • How much space this occupies - if there are padding bits/bytes and where they are located in memory.

    • Where the bit is located in memory. Not defined and also depends on endianess.

    • Whether an int:n bitfield is to be regarded as signed or unsigned.


    Regarding the last part, C17 6.7.2.1/10 says:




    A bit-field is interpreted as having a signed or unsigned integer type consisting of the
    specified number of bits 125)




    Non-normative note explaining the above:




    125) As specified in 6.7.2 above, if the actual type specifier used is int or a typedef-name defined as int,
    then it is implementation-defined whether the bit-field is signed or unsigned.




    In case the bitfield is to be regarded as signed int and you make a bit of size 1, then there is no room for data, only for the sign bit. This is the reason why your program might give weird results on some compilers.



    Good practice:




    • Never use bit-fields for any purpose.

    • Avoid using signed int type for any form of bit manipulation.






    share|improve this answer



















    • 2




      At work we have static_asserts on the size and address of bitfields just to make sure that they are not padded. We use bitfields for hardware registers in our firmware.
      – Michael
      8 hours ago















    up vote
    34
    down vote













    Bit-fields are incredibly poorly defined by the standard. Given this code struct mystruct {int enabled:1;};, then we don't know:




    • How much space this occupies - if there are padding bits/bytes and where they are located in memory.

    • Where the bit is located in memory. Not defined and also depends on endianess.

    • Whether an int:n bitfield is to be regarded as signed or unsigned.


    Regarding the last part, C17 6.7.2.1/10 says:




    A bit-field is interpreted as having a signed or unsigned integer type consisting of the
    specified number of bits 125)




    Non-normative note explaining the above:




    125) As specified in 6.7.2 above, if the actual type specifier used is int or a typedef-name defined as int,
    then it is implementation-defined whether the bit-field is signed or unsigned.




    In case the bitfield is to be regarded as signed int and you make a bit of size 1, then there is no room for data, only for the sign bit. This is the reason why your program might give weird results on some compilers.



    Good practice:




    • Never use bit-fields for any purpose.

    • Avoid using signed int type for any form of bit manipulation.






    share|improve this answer



















    • 2




      At work we have static_asserts on the size and address of bitfields just to make sure that they are not padded. We use bitfields for hardware registers in our firmware.
      – Michael
      8 hours ago













    up vote
    34
    down vote










    up vote
    34
    down vote









    Bit-fields are incredibly poorly defined by the standard. Given this code struct mystruct {int enabled:1;};, then we don't know:




    • How much space this occupies - if there are padding bits/bytes and where they are located in memory.

    • Where the bit is located in memory. Not defined and also depends on endianess.

    • Whether an int:n bitfield is to be regarded as signed or unsigned.


    Regarding the last part, C17 6.7.2.1/10 says:




    A bit-field is interpreted as having a signed or unsigned integer type consisting of the
    specified number of bits 125)




    Non-normative note explaining the above:




    125) As specified in 6.7.2 above, if the actual type specifier used is int or a typedef-name defined as int,
    then it is implementation-defined whether the bit-field is signed or unsigned.




    In case the bitfield is to be regarded as signed int and you make a bit of size 1, then there is no room for data, only for the sign bit. This is the reason why your program might give weird results on some compilers.



    Good practice:




    • Never use bit-fields for any purpose.

    • Avoid using signed int type for any form of bit manipulation.






    share|improve this answer














    Bit-fields are incredibly poorly defined by the standard. Given this code struct mystruct {int enabled:1;};, then we don't know:




    • How much space this occupies - if there are padding bits/bytes and where they are located in memory.

    • Where the bit is located in memory. Not defined and also depends on endianess.

    • Whether an int:n bitfield is to be regarded as signed or unsigned.


    Regarding the last part, C17 6.7.2.1/10 says:




    A bit-field is interpreted as having a signed or unsigned integer type consisting of the
    specified number of bits 125)




    Non-normative note explaining the above:




    125) As specified in 6.7.2 above, if the actual type specifier used is int or a typedef-name defined as int,
    then it is implementation-defined whether the bit-field is signed or unsigned.




    In case the bitfield is to be regarded as signed int and you make a bit of size 1, then there is no room for data, only for the sign bit. This is the reason why your program might give weird results on some compilers.



    Good practice:




    • Never use bit-fields for any purpose.

    • Avoid using signed int type for any form of bit manipulation.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 13 hours ago

























    answered 13 hours ago









    Lundin

    106k17156260




    106k17156260








    • 2




      At work we have static_asserts on the size and address of bitfields just to make sure that they are not padded. We use bitfields for hardware registers in our firmware.
      – Michael
      8 hours ago














    • 2




      At work we have static_asserts on the size and address of bitfields just to make sure that they are not padded. We use bitfields for hardware registers in our firmware.
      – Michael
      8 hours ago








    2




    2




    At work we have static_asserts on the size and address of bitfields just to make sure that they are not padded. We use bitfields for hardware registers in our firmware.
    – Michael
    8 hours ago




    At work we have static_asserts on the size and address of bitfields just to make sure that they are not padded. We use bitfields for hardware registers in our firmware.
    – Michael
    8 hours ago












    up vote
    20
    down vote














    I am unable to understand, how is it possible that we set something and then it doesn't show up as it is.




    Are you asking why it compiles vs. gives you an error?



    Yes, it should ideally give you an error. And it does, if you use your compiler's warnings. In GCC, with -Werror -Wall -pedantic:



    main.cpp: In function 'int main()':
    main.cpp:7:15: error: overflow in conversion from 'int' to 'signed char:1'
    changes value from '1' to '-1' [-Werror=overflow]
    s.enabled = 1;
    ^


    The reasoning for why this is left up to being implementation-defined vs. an error may have more to do with historical usages, where requiring a cast would mean breaking old code. The authors of the standard may believe warnings were enough to pick up the slack for those concerned.



    To throw in some prescriptivism, I'll echo @Lundin's statement: "Never use bit-fields for any purpose." If you have the kind of good reasons to get low-level and specific about your memory layout details that would get you to thinking you needed bitfields in the first place, the other associated requirements you almost certainly have will run up against their underspecification.



    (TL;DR - If you're sophisticated enough to legitimately "need" bit-fields, they're not well-defined enough to serve you.)






    share|improve this answer



















    • 8




      The authors of the standard were on holidays the day the bit-field chapter was designed. So the janitor had to do it. There is no rationale about anything regarding how bit-fields are designed.
      – Lundin
      13 hours ago








    • 5




      There is no coherent technical rationale. But that leads me to conclude that there was a political rationale: to avoid making any of the existing code or implementations incorrect. But the result is that there's very little about bitfields that you can rely upon.
      – John Bollinger
      13 hours ago






    • 1




      @JohnBollinger There was definitely politics in place, that caused a lot of damage to C90. I once spoke with a member of the committee who explained the source of lots of the crap - the ISO standard could not be allowed to favour certain existing technologies. This is why we are stuck with moronic things like support for 1's complement and signed magnitude, implementation-defined signedness of char, support for bytes that aren't 8 bits etc etc. They weren't allowed to give moronic computers a market disadvantage.
      – Lundin
      13 hours ago








    • 1




      @Lundin It would be interesting to see a collection of writeups and post-mortems from people who believed tradeoffs had been made in error, and why. I wonder how much study of these "we did that last time, and it did/didn't work out" has become institutional knowledge to inform the next such case, vs. just stories in people's heads.
      – HostileFork
      12 hours ago






    • 1




      This is still listed as point no. 1 of the original principles of C in the C2x Charter: "Existing code is important, existing implementations are not." ... "no one implementation was held up as the exemplar by which to define C: It is assumed that all existing implementations must change somewhat to conform to the Standard."
      – Leushenko
      12 hours ago















    up vote
    20
    down vote














    I am unable to understand, how is it possible that we set something and then it doesn't show up as it is.




    Are you asking why it compiles vs. gives you an error?



    Yes, it should ideally give you an error. And it does, if you use your compiler's warnings. In GCC, with -Werror -Wall -pedantic:



    main.cpp: In function 'int main()':
    main.cpp:7:15: error: overflow in conversion from 'int' to 'signed char:1'
    changes value from '1' to '-1' [-Werror=overflow]
    s.enabled = 1;
    ^


    The reasoning for why this is left up to being implementation-defined vs. an error may have more to do with historical usages, where requiring a cast would mean breaking old code. The authors of the standard may believe warnings were enough to pick up the slack for those concerned.



    To throw in some prescriptivism, I'll echo @Lundin's statement: "Never use bit-fields for any purpose." If you have the kind of good reasons to get low-level and specific about your memory layout details that would get you to thinking you needed bitfields in the first place, the other associated requirements you almost certainly have will run up against their underspecification.



    (TL;DR - If you're sophisticated enough to legitimately "need" bit-fields, they're not well-defined enough to serve you.)






    share|improve this answer



















    • 8




      The authors of the standard were on holidays the day the bit-field chapter was designed. So the janitor had to do it. There is no rationale about anything regarding how bit-fields are designed.
      – Lundin
      13 hours ago








    • 5




      There is no coherent technical rationale. But that leads me to conclude that there was a political rationale: to avoid making any of the existing code or implementations incorrect. But the result is that there's very little about bitfields that you can rely upon.
      – John Bollinger
      13 hours ago






    • 1




      @JohnBollinger There was definitely politics in place, that caused a lot of damage to C90. I once spoke with a member of the committee who explained the source of lots of the crap - the ISO standard could not be allowed to favour certain existing technologies. This is why we are stuck with moronic things like support for 1's complement and signed magnitude, implementation-defined signedness of char, support for bytes that aren't 8 bits etc etc. They weren't allowed to give moronic computers a market disadvantage.
      – Lundin
      13 hours ago








    • 1




      @Lundin It would be interesting to see a collection of writeups and post-mortems from people who believed tradeoffs had been made in error, and why. I wonder how much study of these "we did that last time, and it did/didn't work out" has become institutional knowledge to inform the next such case, vs. just stories in people's heads.
      – HostileFork
      12 hours ago






    • 1




      This is still listed as point no. 1 of the original principles of C in the C2x Charter: "Existing code is important, existing implementations are not." ... "no one implementation was held up as the exemplar by which to define C: It is assumed that all existing implementations must change somewhat to conform to the Standard."
      – Leushenko
      12 hours ago













    up vote
    20
    down vote










    up vote
    20
    down vote










    I am unable to understand, how is it possible that we set something and then it doesn't show up as it is.




    Are you asking why it compiles vs. gives you an error?



    Yes, it should ideally give you an error. And it does, if you use your compiler's warnings. In GCC, with -Werror -Wall -pedantic:



    main.cpp: In function 'int main()':
    main.cpp:7:15: error: overflow in conversion from 'int' to 'signed char:1'
    changes value from '1' to '-1' [-Werror=overflow]
    s.enabled = 1;
    ^


    The reasoning for why this is left up to being implementation-defined vs. an error may have more to do with historical usages, where requiring a cast would mean breaking old code. The authors of the standard may believe warnings were enough to pick up the slack for those concerned.



    To throw in some prescriptivism, I'll echo @Lundin's statement: "Never use bit-fields for any purpose." If you have the kind of good reasons to get low-level and specific about your memory layout details that would get you to thinking you needed bitfields in the first place, the other associated requirements you almost certainly have will run up against their underspecification.



    (TL;DR - If you're sophisticated enough to legitimately "need" bit-fields, they're not well-defined enough to serve you.)






    share|improve this answer















    I am unable to understand, how is it possible that we set something and then it doesn't show up as it is.




    Are you asking why it compiles vs. gives you an error?



    Yes, it should ideally give you an error. And it does, if you use your compiler's warnings. In GCC, with -Werror -Wall -pedantic:



    main.cpp: In function 'int main()':
    main.cpp:7:15: error: overflow in conversion from 'int' to 'signed char:1'
    changes value from '1' to '-1' [-Werror=overflow]
    s.enabled = 1;
    ^


    The reasoning for why this is left up to being implementation-defined vs. an error may have more to do with historical usages, where requiring a cast would mean breaking old code. The authors of the standard may believe warnings were enough to pick up the slack for those concerned.



    To throw in some prescriptivism, I'll echo @Lundin's statement: "Never use bit-fields for any purpose." If you have the kind of good reasons to get low-level and specific about your memory layout details that would get you to thinking you needed bitfields in the first place, the other associated requirements you almost certainly have will run up against their underspecification.



    (TL;DR - If you're sophisticated enough to legitimately "need" bit-fields, they're not well-defined enough to serve you.)







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 9 hours ago

























    answered 13 hours ago









    HostileFork

    25k776132




    25k776132








    • 8




      The authors of the standard were on holidays the day the bit-field chapter was designed. So the janitor had to do it. There is no rationale about anything regarding how bit-fields are designed.
      – Lundin
      13 hours ago








    • 5




      There is no coherent technical rationale. But that leads me to conclude that there was a political rationale: to avoid making any of the existing code or implementations incorrect. But the result is that there's very little about bitfields that you can rely upon.
      – John Bollinger
      13 hours ago






    • 1




      @JohnBollinger There was definitely politics in place, that caused a lot of damage to C90. I once spoke with a member of the committee who explained the source of lots of the crap - the ISO standard could not be allowed to favour certain existing technologies. This is why we are stuck with moronic things like support for 1's complement and signed magnitude, implementation-defined signedness of char, support for bytes that aren't 8 bits etc etc. They weren't allowed to give moronic computers a market disadvantage.
      – Lundin
      13 hours ago








    • 1




      @Lundin It would be interesting to see a collection of writeups and post-mortems from people who believed tradeoffs had been made in error, and why. I wonder how much study of these "we did that last time, and it did/didn't work out" has become institutional knowledge to inform the next such case, vs. just stories in people's heads.
      – HostileFork
      12 hours ago






    • 1




      This is still listed as point no. 1 of the original principles of C in the C2x Charter: "Existing code is important, existing implementations are not." ... "no one implementation was held up as the exemplar by which to define C: It is assumed that all existing implementations must change somewhat to conform to the Standard."
      – Leushenko
      12 hours ago














    • 8




      The authors of the standard were on holidays the day the bit-field chapter was designed. So the janitor had to do it. There is no rationale about anything regarding how bit-fields are designed.
      – Lundin
      13 hours ago








    • 5




      There is no coherent technical rationale. But that leads me to conclude that there was a political rationale: to avoid making any of the existing code or implementations incorrect. But the result is that there's very little about bitfields that you can rely upon.
      – John Bollinger
      13 hours ago






    • 1




      @JohnBollinger There was definitely politics in place, that caused a lot of damage to C90. I once spoke with a member of the committee who explained the source of lots of the crap - the ISO standard could not be allowed to favour certain existing technologies. This is why we are stuck with moronic things like support for 1's complement and signed magnitude, implementation-defined signedness of char, support for bytes that aren't 8 bits etc etc. They weren't allowed to give moronic computers a market disadvantage.
      – Lundin
      13 hours ago








    • 1




      @Lundin It would be interesting to see a collection of writeups and post-mortems from people who believed tradeoffs had been made in error, and why. I wonder how much study of these "we did that last time, and it did/didn't work out" has become institutional knowledge to inform the next such case, vs. just stories in people's heads.
      – HostileFork
      12 hours ago






    • 1




      This is still listed as point no. 1 of the original principles of C in the C2x Charter: "Existing code is important, existing implementations are not." ... "no one implementation was held up as the exemplar by which to define C: It is assumed that all existing implementations must change somewhat to conform to the Standard."
      – Leushenko
      12 hours ago








    8




    8




    The authors of the standard were on holidays the day the bit-field chapter was designed. So the janitor had to do it. There is no rationale about anything regarding how bit-fields are designed.
    – Lundin
    13 hours ago






    The authors of the standard were on holidays the day the bit-field chapter was designed. So the janitor had to do it. There is no rationale about anything regarding how bit-fields are designed.
    – Lundin
    13 hours ago






    5




    5




    There is no coherent technical rationale. But that leads me to conclude that there was a political rationale: to avoid making any of the existing code or implementations incorrect. But the result is that there's very little about bitfields that you can rely upon.
    – John Bollinger
    13 hours ago




    There is no coherent technical rationale. But that leads me to conclude that there was a political rationale: to avoid making any of the existing code or implementations incorrect. But the result is that there's very little about bitfields that you can rely upon.
    – John Bollinger
    13 hours ago




    1




    1




    @JohnBollinger There was definitely politics in place, that caused a lot of damage to C90. I once spoke with a member of the committee who explained the source of lots of the crap - the ISO standard could not be allowed to favour certain existing technologies. This is why we are stuck with moronic things like support for 1's complement and signed magnitude, implementation-defined signedness of char, support for bytes that aren't 8 bits etc etc. They weren't allowed to give moronic computers a market disadvantage.
    – Lundin
    13 hours ago






    @JohnBollinger There was definitely politics in place, that caused a lot of damage to C90. I once spoke with a member of the committee who explained the source of lots of the crap - the ISO standard could not be allowed to favour certain existing technologies. This is why we are stuck with moronic things like support for 1's complement and signed magnitude, implementation-defined signedness of char, support for bytes that aren't 8 bits etc etc. They weren't allowed to give moronic computers a market disadvantage.
    – Lundin
    13 hours ago






    1




    1




    @Lundin It would be interesting to see a collection of writeups and post-mortems from people who believed tradeoffs had been made in error, and why. I wonder how much study of these "we did that last time, and it did/didn't work out" has become institutional knowledge to inform the next such case, vs. just stories in people's heads.
    – HostileFork
    12 hours ago




    @Lundin It would be interesting to see a collection of writeups and post-mortems from people who believed tradeoffs had been made in error, and why. I wonder how much study of these "we did that last time, and it did/didn't work out" has become institutional knowledge to inform the next such case, vs. just stories in people's heads.
    – HostileFork
    12 hours ago




    1




    1




    This is still listed as point no. 1 of the original principles of C in the C2x Charter: "Existing code is important, existing implementations are not." ... "no one implementation was held up as the exemplar by which to define C: It is assumed that all existing implementations must change somewhat to conform to the Standard."
    – Leushenko
    12 hours ago




    This is still listed as point no. 1 of the original principles of C in the C2x Charter: "Existing code is important, existing implementations are not." ... "no one implementation was held up as the exemplar by which to define C: It is assumed that all existing implementations must change somewhat to conform to the Standard."
    – Leushenko
    12 hours ago










    up vote
    11
    down vote













    This is implementation defined behavior. I am making the assumption that the machines you are running this on use twos-compliment signed integers and treat int in this case as a signed integer to explain why you don't enter if true part of the if statement.



    struct mystruct { int enabled:1; };


    declares enable as a 1 bit bit-field. Since it is signed, the valid values are -1 and 0. Setting the field to 1 overflows that bit going back to -1 (this is undefined behavior)



    Essentially when dealing with a signed bit-field the max value is 2^(bits - 1) - 1 which is 0 in this case.






    share|improve this answer























    • "ince it is signed, the valid values are -1 and 0". Who said it is signed? It's not defined but implementation-defined behavior. If it is signed, then the valid values are - and +. 2's complement doesn't matter.
      – Lundin
      13 hours ago








    • 3




      @Lundin A 1 bit twos compliment number only has two possible values. If the bit is set, then since it is the sign bit, it is -1. If it isn't set then it is "positive" 0. I know this is implementation defined, I'm just explaining the results using the most common implantation
      – NathanOliver
      13 hours ago










    • The key here is rather that 2's complement or any other signed form cannot function with a single bit available.
      – Lundin
      13 hours ago






    • 1




      @JohnBollinger I understand that. That's why I have the discliamer that this is implementation defined. At least for the big 3 they all treat int as signed in this case. It is a shame that bit-fields are so under specified. It's basically here is this feature, consult your compiler on how to use it.
      – NathanOliver
      13 hours ago








    • 1




      @Lundin, the standard's wording for the representation of signed integers can perfectly well handle the case where there are zero value bits, at least in two of the three allowed alternatives. This works because it assigns (negative) place values to sign bits, rather than giving them an algorithmic interpretation.
      – John Bollinger
      13 hours ago

















    up vote
    11
    down vote













    This is implementation defined behavior. I am making the assumption that the machines you are running this on use twos-compliment signed integers and treat int in this case as a signed integer to explain why you don't enter if true part of the if statement.



    struct mystruct { int enabled:1; };


    declares enable as a 1 bit bit-field. Since it is signed, the valid values are -1 and 0. Setting the field to 1 overflows that bit going back to -1 (this is undefined behavior)



    Essentially when dealing with a signed bit-field the max value is 2^(bits - 1) - 1 which is 0 in this case.






    share|improve this answer























    • "ince it is signed, the valid values are -1 and 0". Who said it is signed? It's not defined but implementation-defined behavior. If it is signed, then the valid values are - and +. 2's complement doesn't matter.
      – Lundin
      13 hours ago








    • 3




      @Lundin A 1 bit twos compliment number only has two possible values. If the bit is set, then since it is the sign bit, it is -1. If it isn't set then it is "positive" 0. I know this is implementation defined, I'm just explaining the results using the most common implantation
      – NathanOliver
      13 hours ago










    • The key here is rather that 2's complement or any other signed form cannot function with a single bit available.
      – Lundin
      13 hours ago






    • 1




      @JohnBollinger I understand that. That's why I have the discliamer that this is implementation defined. At least for the big 3 they all treat int as signed in this case. It is a shame that bit-fields are so under specified. It's basically here is this feature, consult your compiler on how to use it.
      – NathanOliver
      13 hours ago








    • 1




      @Lundin, the standard's wording for the representation of signed integers can perfectly well handle the case where there are zero value bits, at least in two of the three allowed alternatives. This works because it assigns (negative) place values to sign bits, rather than giving them an algorithmic interpretation.
      – John Bollinger
      13 hours ago















    up vote
    11
    down vote










    up vote
    11
    down vote









    This is implementation defined behavior. I am making the assumption that the machines you are running this on use twos-compliment signed integers and treat int in this case as a signed integer to explain why you don't enter if true part of the if statement.



    struct mystruct { int enabled:1; };


    declares enable as a 1 bit bit-field. Since it is signed, the valid values are -1 and 0. Setting the field to 1 overflows that bit going back to -1 (this is undefined behavior)



    Essentially when dealing with a signed bit-field the max value is 2^(bits - 1) - 1 which is 0 in this case.






    share|improve this answer














    This is implementation defined behavior. I am making the assumption that the machines you are running this on use twos-compliment signed integers and treat int in this case as a signed integer to explain why you don't enter if true part of the if statement.



    struct mystruct { int enabled:1; };


    declares enable as a 1 bit bit-field. Since it is signed, the valid values are -1 and 0. Setting the field to 1 overflows that bit going back to -1 (this is undefined behavior)



    Essentially when dealing with a signed bit-field the max value is 2^(bits - 1) - 1 which is 0 in this case.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 12 hours ago









    Community

    11




    11










    answered 13 hours ago









    NathanOliver

    86.1k15118179




    86.1k15118179












    • "ince it is signed, the valid values are -1 and 0". Who said it is signed? It's not defined but implementation-defined behavior. If it is signed, then the valid values are - and +. 2's complement doesn't matter.
      – Lundin
      13 hours ago








    • 3




      @Lundin A 1 bit twos compliment number only has two possible values. If the bit is set, then since it is the sign bit, it is -1. If it isn't set then it is "positive" 0. I know this is implementation defined, I'm just explaining the results using the most common implantation
      – NathanOliver
      13 hours ago










    • The key here is rather that 2's complement or any other signed form cannot function with a single bit available.
      – Lundin
      13 hours ago






    • 1




      @JohnBollinger I understand that. That's why I have the discliamer that this is implementation defined. At least for the big 3 they all treat int as signed in this case. It is a shame that bit-fields are so under specified. It's basically here is this feature, consult your compiler on how to use it.
      – NathanOliver
      13 hours ago








    • 1




      @Lundin, the standard's wording for the representation of signed integers can perfectly well handle the case where there are zero value bits, at least in two of the three allowed alternatives. This works because it assigns (negative) place values to sign bits, rather than giving them an algorithmic interpretation.
      – John Bollinger
      13 hours ago




















    • "ince it is signed, the valid values are -1 and 0". Who said it is signed? It's not defined but implementation-defined behavior. If it is signed, then the valid values are - and +. 2's complement doesn't matter.
      – Lundin
      13 hours ago








    • 3




      @Lundin A 1 bit twos compliment number only has two possible values. If the bit is set, then since it is the sign bit, it is -1. If it isn't set then it is "positive" 0. I know this is implementation defined, I'm just explaining the results using the most common implantation
      – NathanOliver
      13 hours ago










    • The key here is rather that 2's complement or any other signed form cannot function with a single bit available.
      – Lundin
      13 hours ago






    • 1




      @JohnBollinger I understand that. That's why I have the discliamer that this is implementation defined. At least for the big 3 they all treat int as signed in this case. It is a shame that bit-fields are so under specified. It's basically here is this feature, consult your compiler on how to use it.
      – NathanOliver
      13 hours ago








    • 1




      @Lundin, the standard's wording for the representation of signed integers can perfectly well handle the case where there are zero value bits, at least in two of the three allowed alternatives. This works because it assigns (negative) place values to sign bits, rather than giving them an algorithmic interpretation.
      – John Bollinger
      13 hours ago


















    "ince it is signed, the valid values are -1 and 0". Who said it is signed? It's not defined but implementation-defined behavior. If it is signed, then the valid values are - and +. 2's complement doesn't matter.
    – Lundin
    13 hours ago






    "ince it is signed, the valid values are -1 and 0". Who said it is signed? It's not defined but implementation-defined behavior. If it is signed, then the valid values are - and +. 2's complement doesn't matter.
    – Lundin
    13 hours ago






    3




    3




    @Lundin A 1 bit twos compliment number only has two possible values. If the bit is set, then since it is the sign bit, it is -1. If it isn't set then it is "positive" 0. I know this is implementation defined, I'm just explaining the results using the most common implantation
    – NathanOliver
    13 hours ago




    @Lundin A 1 bit twos compliment number only has two possible values. If the bit is set, then since it is the sign bit, it is -1. If it isn't set then it is "positive" 0. I know this is implementation defined, I'm just explaining the results using the most common implantation
    – NathanOliver
    13 hours ago












    The key here is rather that 2's complement or any other signed form cannot function with a single bit available.
    – Lundin
    13 hours ago




    The key here is rather that 2's complement or any other signed form cannot function with a single bit available.
    – Lundin
    13 hours ago




    1




    1




    @JohnBollinger I understand that. That's why I have the discliamer that this is implementation defined. At least for the big 3 they all treat int as signed in this case. It is a shame that bit-fields are so under specified. It's basically here is this feature, consult your compiler on how to use it.
    – NathanOliver
    13 hours ago






    @JohnBollinger I understand that. That's why I have the discliamer that this is implementation defined. At least for the big 3 they all treat int as signed in this case. It is a shame that bit-fields are so under specified. It's basically here is this feature, consult your compiler on how to use it.
    – NathanOliver
    13 hours ago






    1




    1




    @Lundin, the standard's wording for the representation of signed integers can perfectly well handle the case where there are zero value bits, at least in two of the three allowed alternatives. This works because it assigns (negative) place values to sign bits, rather than giving them an algorithmic interpretation.
    – John Bollinger
    13 hours ago






    @Lundin, the standard's wording for the representation of signed integers can perfectly well handle the case where there are zero value bits, at least in two of the three allowed alternatives. This works because it assigns (negative) place values to sign bits, rather than giving them an algorithmic interpretation.
    – John Bollinger
    13 hours ago












    up vote
    3
    down vote













    You could think of it as that in the 2's complement system, the left-most bit is the sign bit. Any signed integer with the left-most bit set is thus a negative value.



    If you have a 1-bit signed integer, it has only the sign bit. So assigning 1 to that single bit can only set the sign bit. So, when reading it back, the value is interpreted as negative and so is -1.



    The values a 1 bit signed integer can hold is -2^(n-1)= -2^(1-1)= -2^0= -1 and 2^n-1= 2^1-1=0






    share|improve this answer

























      up vote
      3
      down vote













      You could think of it as that in the 2's complement system, the left-most bit is the sign bit. Any signed integer with the left-most bit set is thus a negative value.



      If you have a 1-bit signed integer, it has only the sign bit. So assigning 1 to that single bit can only set the sign bit. So, when reading it back, the value is interpreted as negative and so is -1.



      The values a 1 bit signed integer can hold is -2^(n-1)= -2^(1-1)= -2^0= -1 and 2^n-1= 2^1-1=0






      share|improve this answer























        up vote
        3
        down vote










        up vote
        3
        down vote









        You could think of it as that in the 2's complement system, the left-most bit is the sign bit. Any signed integer with the left-most bit set is thus a negative value.



        If you have a 1-bit signed integer, it has only the sign bit. So assigning 1 to that single bit can only set the sign bit. So, when reading it back, the value is interpreted as negative and so is -1.



        The values a 1 bit signed integer can hold is -2^(n-1)= -2^(1-1)= -2^0= -1 and 2^n-1= 2^1-1=0






        share|improve this answer












        You could think of it as that in the 2's complement system, the left-most bit is the sign bit. Any signed integer with the left-most bit set is thus a negative value.



        If you have a 1-bit signed integer, it has only the sign bit. So assigning 1 to that single bit can only set the sign bit. So, when reading it back, the value is interpreted as negative and so is -1.



        The values a 1 bit signed integer can hold is -2^(n-1)= -2^(1-1)= -2^0= -1 and 2^n-1= 2^1-1=0







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 13 hours ago









        Paul Ogilvie

        17.1k11234




        17.1k11234






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53853540%2fwhy-is-assigning-a-value-to-a-bit-field-not-giving-the-same-value-back%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Quarter-circle Tiles

            build a pushdown automaton that recognizes the reverse language of a given pushdown automaton?

            Mont Emei