left shift count >= width of type in C macro












1















I have written a C Macro to set/unset Bits in a uint32 variable. Here are the definitions of the macros:



extern uint32_t error_field, error_field2;
#define SET_ERROR_BIT(x) do{
if(x < 0 || x >63){
break;
}
if(((uint32_t)x)<32U){
(error_field |= ((uint32_t)1U << ((uint32_t)x)));
break;
} else if(((uint32_t)x)<64U){
(error_field2 |= ((uint32_t)1U<<(((uint32_t)x)-32U)));
}
}while(0)

#define RESET_ERROR_BIT(x) do{
if(((uint32_t)x)<32U){
(error_field &= ~((uint32_t)1U<<((uint32_t)x)));
break;
} else if(((uint32_t)x) < 64U){
(error_field2 &= ~((uint32_t)1U<<(((uint32_t)x)-32U)));
}
} while(0)


I am passing a field of an enumeration, that looks like this:



enum error_bits {
error_chamber01_data = 0,
error_port21_data,
error_port22_data,
error_port23_data,
error_port24_data,
/*this goes on until 47*/
};


This warning is produced:




left shift count >= width of type [-Wshift-count-overflow]




I am calling the Macros like this:



USART2->CR1 |= USART_CR1_RXNEIE;
SET_ERROR_BIT(error_usart2);
/*error_usart2 is 47 in the enum*/
return -1;


I get this warning with every macro, even with those where the left shift count is < 31.



If I use the definition of the macro without the macro, it produces no warning. The behaviour is the same with a 64 bit variable. I am programming a STM32F7 with AC6 STM32 MCU GCC compiler.
I can't figure out why this happens. Can anyone help me?










share|improve this question




















  • 1





    show where the macro is called also

    – LoPiTaL
    Nov 26 '18 at 11:06











  • I have edited the post.

    – Vincent Fartmann
    Nov 26 '18 at 11:09






  • 1





    This (and I really don't mean to cause offence here) truly hideous beast is a classic example of why macros are a bad idea for anything other than simple true/false things in modern C compilers. You could write something far more readable with a function that generally has little performance impact, if any. I always try to optimise for readabilty first :-)

    – paxdiablo
    Nov 26 '18 at 11:09













  • I already thought of writing a function for this, but i want to figure out why the warning is produced

    – Vincent Fartmann
    Nov 26 '18 at 11:12






  • 4





    In the macros, you distinguish two cases, which, on their own, are okay. The warning comes from the branch that isn't executed, where the shift is out of range. (Apparently these disgnostics are issued before the dead branch is eliminated.)

    – M Oehm
    Nov 26 '18 at 11:16


















1















I have written a C Macro to set/unset Bits in a uint32 variable. Here are the definitions of the macros:



extern uint32_t error_field, error_field2;
#define SET_ERROR_BIT(x) do{
if(x < 0 || x >63){
break;
}
if(((uint32_t)x)<32U){
(error_field |= ((uint32_t)1U << ((uint32_t)x)));
break;
} else if(((uint32_t)x)<64U){
(error_field2 |= ((uint32_t)1U<<(((uint32_t)x)-32U)));
}
}while(0)

#define RESET_ERROR_BIT(x) do{
if(((uint32_t)x)<32U){
(error_field &= ~((uint32_t)1U<<((uint32_t)x)));
break;
} else if(((uint32_t)x) < 64U){
(error_field2 &= ~((uint32_t)1U<<(((uint32_t)x)-32U)));
}
} while(0)


I am passing a field of an enumeration, that looks like this:



enum error_bits {
error_chamber01_data = 0,
error_port21_data,
error_port22_data,
error_port23_data,
error_port24_data,
/*this goes on until 47*/
};


This warning is produced:




left shift count >= width of type [-Wshift-count-overflow]




I am calling the Macros like this:



USART2->CR1 |= USART_CR1_RXNEIE;
SET_ERROR_BIT(error_usart2);
/*error_usart2 is 47 in the enum*/
return -1;


I get this warning with every macro, even with those where the left shift count is < 31.



If I use the definition of the macro without the macro, it produces no warning. The behaviour is the same with a 64 bit variable. I am programming a STM32F7 with AC6 STM32 MCU GCC compiler.
I can't figure out why this happens. Can anyone help me?










share|improve this question




















  • 1





    show where the macro is called also

    – LoPiTaL
    Nov 26 '18 at 11:06











  • I have edited the post.

    – Vincent Fartmann
    Nov 26 '18 at 11:09






  • 1





    This (and I really don't mean to cause offence here) truly hideous beast is a classic example of why macros are a bad idea for anything other than simple true/false things in modern C compilers. You could write something far more readable with a function that generally has little performance impact, if any. I always try to optimise for readabilty first :-)

    – paxdiablo
    Nov 26 '18 at 11:09













  • I already thought of writing a function for this, but i want to figure out why the warning is produced

    – Vincent Fartmann
    Nov 26 '18 at 11:12






  • 4





    In the macros, you distinguish two cases, which, on their own, are okay. The warning comes from the branch that isn't executed, where the shift is out of range. (Apparently these disgnostics are issued before the dead branch is eliminated.)

    – M Oehm
    Nov 26 '18 at 11:16
















1












1








1








I have written a C Macro to set/unset Bits in a uint32 variable. Here are the definitions of the macros:



extern uint32_t error_field, error_field2;
#define SET_ERROR_BIT(x) do{
if(x < 0 || x >63){
break;
}
if(((uint32_t)x)<32U){
(error_field |= ((uint32_t)1U << ((uint32_t)x)));
break;
} else if(((uint32_t)x)<64U){
(error_field2 |= ((uint32_t)1U<<(((uint32_t)x)-32U)));
}
}while(0)

#define RESET_ERROR_BIT(x) do{
if(((uint32_t)x)<32U){
(error_field &= ~((uint32_t)1U<<((uint32_t)x)));
break;
} else if(((uint32_t)x) < 64U){
(error_field2 &= ~((uint32_t)1U<<(((uint32_t)x)-32U)));
}
} while(0)


I am passing a field of an enumeration, that looks like this:



enum error_bits {
error_chamber01_data = 0,
error_port21_data,
error_port22_data,
error_port23_data,
error_port24_data,
/*this goes on until 47*/
};


This warning is produced:




left shift count >= width of type [-Wshift-count-overflow]




I am calling the Macros like this:



USART2->CR1 |= USART_CR1_RXNEIE;
SET_ERROR_BIT(error_usart2);
/*error_usart2 is 47 in the enum*/
return -1;


I get this warning with every macro, even with those where the left shift count is < 31.



If I use the definition of the macro without the macro, it produces no warning. The behaviour is the same with a 64 bit variable. I am programming a STM32F7 with AC6 STM32 MCU GCC compiler.
I can't figure out why this happens. Can anyone help me?










share|improve this question
















I have written a C Macro to set/unset Bits in a uint32 variable. Here are the definitions of the macros:



extern uint32_t error_field, error_field2;
#define SET_ERROR_BIT(x) do{
if(x < 0 || x >63){
break;
}
if(((uint32_t)x)<32U){
(error_field |= ((uint32_t)1U << ((uint32_t)x)));
break;
} else if(((uint32_t)x)<64U){
(error_field2 |= ((uint32_t)1U<<(((uint32_t)x)-32U)));
}
}while(0)

#define RESET_ERROR_BIT(x) do{
if(((uint32_t)x)<32U){
(error_field &= ~((uint32_t)1U<<((uint32_t)x)));
break;
} else if(((uint32_t)x) < 64U){
(error_field2 &= ~((uint32_t)1U<<(((uint32_t)x)-32U)));
}
} while(0)


I am passing a field of an enumeration, that looks like this:



enum error_bits {
error_chamber01_data = 0,
error_port21_data,
error_port22_data,
error_port23_data,
error_port24_data,
/*this goes on until 47*/
};


This warning is produced:




left shift count >= width of type [-Wshift-count-overflow]




I am calling the Macros like this:



USART2->CR1 |= USART_CR1_RXNEIE;
SET_ERROR_BIT(error_usart2);
/*error_usart2 is 47 in the enum*/
return -1;


I get this warning with every macro, even with those where the left shift count is < 31.



If I use the definition of the macro without the macro, it produces no warning. The behaviour is the same with a 64 bit variable. I am programming a STM32F7 with AC6 STM32 MCU GCC compiler.
I can't figure out why this happens. Can anyone help me?







c gcc macros stm32






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 26 '18 at 11:10







Vincent Fartmann

















asked Nov 26 '18 at 11:03









Vincent FartmannVincent Fartmann

164




164








  • 1





    show where the macro is called also

    – LoPiTaL
    Nov 26 '18 at 11:06











  • I have edited the post.

    – Vincent Fartmann
    Nov 26 '18 at 11:09






  • 1





    This (and I really don't mean to cause offence here) truly hideous beast is a classic example of why macros are a bad idea for anything other than simple true/false things in modern C compilers. You could write something far more readable with a function that generally has little performance impact, if any. I always try to optimise for readabilty first :-)

    – paxdiablo
    Nov 26 '18 at 11:09













  • I already thought of writing a function for this, but i want to figure out why the warning is produced

    – Vincent Fartmann
    Nov 26 '18 at 11:12






  • 4





    In the macros, you distinguish two cases, which, on their own, are okay. The warning comes from the branch that isn't executed, where the shift is out of range. (Apparently these disgnostics are issued before the dead branch is eliminated.)

    – M Oehm
    Nov 26 '18 at 11:16
















  • 1





    show where the macro is called also

    – LoPiTaL
    Nov 26 '18 at 11:06











  • I have edited the post.

    – Vincent Fartmann
    Nov 26 '18 at 11:09






  • 1





    This (and I really don't mean to cause offence here) truly hideous beast is a classic example of why macros are a bad idea for anything other than simple true/false things in modern C compilers. You could write something far more readable with a function that generally has little performance impact, if any. I always try to optimise for readabilty first :-)

    – paxdiablo
    Nov 26 '18 at 11:09













  • I already thought of writing a function for this, but i want to figure out why the warning is produced

    – Vincent Fartmann
    Nov 26 '18 at 11:12






  • 4





    In the macros, you distinguish two cases, which, on their own, are okay. The warning comes from the branch that isn't executed, where the shift is out of range. (Apparently these disgnostics are issued before the dead branch is eliminated.)

    – M Oehm
    Nov 26 '18 at 11:16










1




1





show where the macro is called also

– LoPiTaL
Nov 26 '18 at 11:06





show where the macro is called also

– LoPiTaL
Nov 26 '18 at 11:06













I have edited the post.

– Vincent Fartmann
Nov 26 '18 at 11:09





I have edited the post.

– Vincent Fartmann
Nov 26 '18 at 11:09




1




1





This (and I really don't mean to cause offence here) truly hideous beast is a classic example of why macros are a bad idea for anything other than simple true/false things in modern C compilers. You could write something far more readable with a function that generally has little performance impact, if any. I always try to optimise for readabilty first :-)

– paxdiablo
Nov 26 '18 at 11:09







This (and I really don't mean to cause offence here) truly hideous beast is a classic example of why macros are a bad idea for anything other than simple true/false things in modern C compilers. You could write something far more readable with a function that generally has little performance impact, if any. I always try to optimise for readabilty first :-)

– paxdiablo
Nov 26 '18 at 11:09















I already thought of writing a function for this, but i want to figure out why the warning is produced

– Vincent Fartmann
Nov 26 '18 at 11:12





I already thought of writing a function for this, but i want to figure out why the warning is produced

– Vincent Fartmann
Nov 26 '18 at 11:12




4




4





In the macros, you distinguish two cases, which, on their own, are okay. The warning comes from the branch that isn't executed, where the shift is out of range. (Apparently these disgnostics are issued before the dead branch is eliminated.)

– M Oehm
Nov 26 '18 at 11:16







In the macros, you distinguish two cases, which, on their own, are okay. The warning comes from the branch that isn't executed, where the shift is out of range. (Apparently these disgnostics are issued before the dead branch is eliminated.)

– M Oehm
Nov 26 '18 at 11:16














3 Answers
3






active

oldest

votes


















2














Probably a problem with the compiler not being able to diagnose correctly, as stated by M Oehm. A workaround could be, instead of using the minus operation, use the remainder operation:



#define _SET_BIT(x, bit) (x) |= 1U<<((bit) % 32U)
#define SET_BIT(x, bit) _SET_BIT(x, (uint32_t)(bit))
#define _SET_ERROR_BIT(x) do{
if((x)<32U){
SET_BIT(error_field, x);
} else if((x)<64U){
SET_BIT(error_field2, x);
}
}while(0)
#define SET_ERROR_BIT(x) _SET_ERROR_BIT((uint32_t)(x))


This way the compiler is finally smart enough to know that the value of x will never exceed 32.



The call to the "_" macro is used in order to force x to always be an uint32_t, inconditionally of the macro call, avoiding the UB of a call with a negative value of x.



Tested in coliru






share|improve this answer


























  • This works fine for numbers <32. For numbers >=32 it produces the same warning: coliru.stacked-crooked.com/a/3d79a452e4a6efda

    – Vincent Fartmann
    Nov 26 '18 at 11:32











  • yes, because the other branch needs also the modulus operation, I update the link

    – LoPiTaL
    Nov 26 '18 at 11:34











  • I have also simplified the macro, removing unnecessary castings and breaks

    – LoPiTaL
    Nov 26 '18 at 11:39











  • I figured out the fault, see the last comment. Thank you!

    – Vincent Fartmann
    Nov 26 '18 at 11:39






  • 1





    Yes, with -1LL that is true, did not see that. Still hole remains, but in a new, and less likely, place such as SET_ERROR_BIT(-0x100000000) as the (uint32_t) cast simply wraps the negative values and then some will end up as 0-63.

    – chux
    Nov 26 '18 at 14:57



















0














Problem:




In the macros, you distinguish two cases, which, on their own, are okay. The warning comes from the branch that isn't executed, where the shift is out of range. (Apparently these diagnostics are issued before the dead branch is eliminated.)
@M Oehm




Solution



Insure shifts are in range 0-31 in both paths regardless of the x value and type of x.



x & 31 is a stronger insurance than x%32 or x%32u. % can result in negative remainders when x < 0 and with a wide enough type.



   #define SET_ERROR_BIT(x) do{
if((x) < 0 || (x) >63){
break;
}
if(((uint32_t)x)<32U){
(error_field |= ((uint32_t)1U << ( (x)&31 )));
break;
} else if(((uint32_t)x)<64U){
(error_field2 |= ((uint32_t)1U<<( (x)&31 )));
}
}while(0)




As a general rule: good to use () around each usage of x.






share|improve this answer

































    0














    Seeing the thread I wanted to indicate a nice (and perhaps cleaner) way to set, reset and toggle the status of a bit in the case of the two unsigned integers as in thread. This code should be OT because uses x that shall be an unsigned int (or an int) and not a enum value.



    I've written the line of code at the end of this answer.



    The code receives as input a number of parameter couples. Each couple of parameter is a letter and a number. The letter may be:




    • S to set a bit

    • R to reset a bit

    • T to toggle a bit


    The number has to be a bit value from 0 to 63. The macros in the code discard each number greater than 63 and nothing is modified into the variables. The negative values haven't been evalued because we suppose a bit value is an unsigned value.



    For Example (if we name the program bitman):



    Executing: bitman S 0 S 1 T 7 S 64 T 7 S 2 T 80 R 1 S 63 S 32 R 63 T 62



    The output will be:



    S 0 00000000-00000001

    S 1 00000000-00000003

    T 7 00000000-00000083

    S 64 00000000-00000083

    T 7 00000000-00000003

    S 2 00000000-00000007

    T 80 00000000-00000007

    R 1 00000000-00000005

    S 63 80000000-00000005

    S 32 80000001-00000005

    R 63 00000001-00000005

    T 62 40000001-00000005



    #include <unistd.h>
    #include <stdio.h>
    #include <stdint.h>
    #include <string.h>

    static uint32_t err1 = 0;
    static uint32_t err2 = 0;

    #define SET_ERROR_BIT(x) (
    ((unsigned)(x)>63)?err1=err1:((x)<32)?
    (err1 |= (1U<<(x))):
    (err2 |= (1U<<((x)-32)))
    )

    #define RESET_ERROR_BIT(x) (
    ((unsigned)(x)>63)?err1=err1:((x)<32)?
    (err1 &= ~(1U<<(x))):
    (err2 &= ~(1U<<((x)-32)))
    )

    #define TOGGLE_ERROR_BIT(x) (
    ((unsigned)(x)>63)?err1=err1:((x)<32)?
    (err1 ^= (1U<<(x))):
    (err2 ^= (1U<<((x)-32)))
    )

    int main(int argc, char *argv)
    {
    int i;
    unsigned int x;

    for(i=1;i<argc;i+=2) {
    x=strtoul(argv[i+1],NULL,0);

    switch (argv[i][0]) {
    case 'S':
    SET_ERROR_BIT(x);
    break;
    case 'T':
    TOGGLE_ERROR_BIT(x);
    break;
    case 'R':
    RESET_ERROR_BIT(x);
    break;
    default:
    break;
    }

    printf("%c %2d %08X-%08Xn",argv[i][0], x, err2, err1);
    }

    return 0;
    }


    The macros are splitted in more then one line, but they are each a one-line code.



    The code main has no error control then if the parameters are not correctly specified the program might be undefined behaviour.






    share|improve this answer


























    • OP's code handled x < 0. This answer, like first one, has vulnerability when x < 0.

      – chux
      Nov 26 '18 at 13:32











    • It's not a vulnerability to avoid the x<0 control, because the input variable should be considered an unsigned at compilation time. If you use an int the code will be compiled with error. If you force the variable at a negative value the code will consider the value as a number greater or equal to 0, so it is sufficient to consider the control on greater than 63.

      – Sir Jo Black
      Nov 26 '18 at 13:37








    • 1





      Disagree with "because the input variable should be considered an unsigned at compilation time". Enumerated values are not certainly unsigned ref and OP wisely wants to prevent possibility with if(x < 0

      – chux
      Nov 26 '18 at 13:42











    • In the code I've implemented the variable x is an unsigned. May be I'm OT.

      – Sir Jo Black
      Nov 26 '18 at 13:46











    • @Chux, I understood your point of view :)

      – Sir Jo Black
      Nov 26 '18 at 13:50












    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%2f53479744%2fleft-shift-count-width-of-type-in-c-macro%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2














    Probably a problem with the compiler not being able to diagnose correctly, as stated by M Oehm. A workaround could be, instead of using the minus operation, use the remainder operation:



    #define _SET_BIT(x, bit) (x) |= 1U<<((bit) % 32U)
    #define SET_BIT(x, bit) _SET_BIT(x, (uint32_t)(bit))
    #define _SET_ERROR_BIT(x) do{
    if((x)<32U){
    SET_BIT(error_field, x);
    } else if((x)<64U){
    SET_BIT(error_field2, x);
    }
    }while(0)
    #define SET_ERROR_BIT(x) _SET_ERROR_BIT((uint32_t)(x))


    This way the compiler is finally smart enough to know that the value of x will never exceed 32.



    The call to the "_" macro is used in order to force x to always be an uint32_t, inconditionally of the macro call, avoiding the UB of a call with a negative value of x.



    Tested in coliru






    share|improve this answer


























    • This works fine for numbers <32. For numbers >=32 it produces the same warning: coliru.stacked-crooked.com/a/3d79a452e4a6efda

      – Vincent Fartmann
      Nov 26 '18 at 11:32











    • yes, because the other branch needs also the modulus operation, I update the link

      – LoPiTaL
      Nov 26 '18 at 11:34











    • I have also simplified the macro, removing unnecessary castings and breaks

      – LoPiTaL
      Nov 26 '18 at 11:39











    • I figured out the fault, see the last comment. Thank you!

      – Vincent Fartmann
      Nov 26 '18 at 11:39






    • 1





      Yes, with -1LL that is true, did not see that. Still hole remains, but in a new, and less likely, place such as SET_ERROR_BIT(-0x100000000) as the (uint32_t) cast simply wraps the negative values and then some will end up as 0-63.

      – chux
      Nov 26 '18 at 14:57
















    2














    Probably a problem with the compiler not being able to diagnose correctly, as stated by M Oehm. A workaround could be, instead of using the minus operation, use the remainder operation:



    #define _SET_BIT(x, bit) (x) |= 1U<<((bit) % 32U)
    #define SET_BIT(x, bit) _SET_BIT(x, (uint32_t)(bit))
    #define _SET_ERROR_BIT(x) do{
    if((x)<32U){
    SET_BIT(error_field, x);
    } else if((x)<64U){
    SET_BIT(error_field2, x);
    }
    }while(0)
    #define SET_ERROR_BIT(x) _SET_ERROR_BIT((uint32_t)(x))


    This way the compiler is finally smart enough to know that the value of x will never exceed 32.



    The call to the "_" macro is used in order to force x to always be an uint32_t, inconditionally of the macro call, avoiding the UB of a call with a negative value of x.



    Tested in coliru






    share|improve this answer


























    • This works fine for numbers <32. For numbers >=32 it produces the same warning: coliru.stacked-crooked.com/a/3d79a452e4a6efda

      – Vincent Fartmann
      Nov 26 '18 at 11:32











    • yes, because the other branch needs also the modulus operation, I update the link

      – LoPiTaL
      Nov 26 '18 at 11:34











    • I have also simplified the macro, removing unnecessary castings and breaks

      – LoPiTaL
      Nov 26 '18 at 11:39











    • I figured out the fault, see the last comment. Thank you!

      – Vincent Fartmann
      Nov 26 '18 at 11:39






    • 1





      Yes, with -1LL that is true, did not see that. Still hole remains, but in a new, and less likely, place such as SET_ERROR_BIT(-0x100000000) as the (uint32_t) cast simply wraps the negative values and then some will end up as 0-63.

      – chux
      Nov 26 '18 at 14:57














    2












    2








    2







    Probably a problem with the compiler not being able to diagnose correctly, as stated by M Oehm. A workaround could be, instead of using the minus operation, use the remainder operation:



    #define _SET_BIT(x, bit) (x) |= 1U<<((bit) % 32U)
    #define SET_BIT(x, bit) _SET_BIT(x, (uint32_t)(bit))
    #define _SET_ERROR_BIT(x) do{
    if((x)<32U){
    SET_BIT(error_field, x);
    } else if((x)<64U){
    SET_BIT(error_field2, x);
    }
    }while(0)
    #define SET_ERROR_BIT(x) _SET_ERROR_BIT((uint32_t)(x))


    This way the compiler is finally smart enough to know that the value of x will never exceed 32.



    The call to the "_" macro is used in order to force x to always be an uint32_t, inconditionally of the macro call, avoiding the UB of a call with a negative value of x.



    Tested in coliru






    share|improve this answer















    Probably a problem with the compiler not being able to diagnose correctly, as stated by M Oehm. A workaround could be, instead of using the minus operation, use the remainder operation:



    #define _SET_BIT(x, bit) (x) |= 1U<<((bit) % 32U)
    #define SET_BIT(x, bit) _SET_BIT(x, (uint32_t)(bit))
    #define _SET_ERROR_BIT(x) do{
    if((x)<32U){
    SET_BIT(error_field, x);
    } else if((x)<64U){
    SET_BIT(error_field2, x);
    }
    }while(0)
    #define SET_ERROR_BIT(x) _SET_ERROR_BIT((uint32_t)(x))


    This way the compiler is finally smart enough to know that the value of x will never exceed 32.



    The call to the "_" macro is used in order to force x to always be an uint32_t, inconditionally of the macro call, avoiding the UB of a call with a negative value of x.



    Tested in coliru







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 26 '18 at 14:05

























    answered Nov 26 '18 at 11:23









    LoPiTaLLoPiTaL

    1,819914




    1,819914













    • This works fine for numbers <32. For numbers >=32 it produces the same warning: coliru.stacked-crooked.com/a/3d79a452e4a6efda

      – Vincent Fartmann
      Nov 26 '18 at 11:32











    • yes, because the other branch needs also the modulus operation, I update the link

      – LoPiTaL
      Nov 26 '18 at 11:34











    • I have also simplified the macro, removing unnecessary castings and breaks

      – LoPiTaL
      Nov 26 '18 at 11:39











    • I figured out the fault, see the last comment. Thank you!

      – Vincent Fartmann
      Nov 26 '18 at 11:39






    • 1





      Yes, with -1LL that is true, did not see that. Still hole remains, but in a new, and less likely, place such as SET_ERROR_BIT(-0x100000000) as the (uint32_t) cast simply wraps the negative values and then some will end up as 0-63.

      – chux
      Nov 26 '18 at 14:57



















    • This works fine for numbers <32. For numbers >=32 it produces the same warning: coliru.stacked-crooked.com/a/3d79a452e4a6efda

      – Vincent Fartmann
      Nov 26 '18 at 11:32











    • yes, because the other branch needs also the modulus operation, I update the link

      – LoPiTaL
      Nov 26 '18 at 11:34











    • I have also simplified the macro, removing unnecessary castings and breaks

      – LoPiTaL
      Nov 26 '18 at 11:39











    • I figured out the fault, see the last comment. Thank you!

      – Vincent Fartmann
      Nov 26 '18 at 11:39






    • 1





      Yes, with -1LL that is true, did not see that. Still hole remains, but in a new, and less likely, place such as SET_ERROR_BIT(-0x100000000) as the (uint32_t) cast simply wraps the negative values and then some will end up as 0-63.

      – chux
      Nov 26 '18 at 14:57

















    This works fine for numbers <32. For numbers >=32 it produces the same warning: coliru.stacked-crooked.com/a/3d79a452e4a6efda

    – Vincent Fartmann
    Nov 26 '18 at 11:32





    This works fine for numbers <32. For numbers >=32 it produces the same warning: coliru.stacked-crooked.com/a/3d79a452e4a6efda

    – Vincent Fartmann
    Nov 26 '18 at 11:32













    yes, because the other branch needs also the modulus operation, I update the link

    – LoPiTaL
    Nov 26 '18 at 11:34





    yes, because the other branch needs also the modulus operation, I update the link

    – LoPiTaL
    Nov 26 '18 at 11:34













    I have also simplified the macro, removing unnecessary castings and breaks

    – LoPiTaL
    Nov 26 '18 at 11:39





    I have also simplified the macro, removing unnecessary castings and breaks

    – LoPiTaL
    Nov 26 '18 at 11:39













    I figured out the fault, see the last comment. Thank you!

    – Vincent Fartmann
    Nov 26 '18 at 11:39





    I figured out the fault, see the last comment. Thank you!

    – Vincent Fartmann
    Nov 26 '18 at 11:39




    1




    1





    Yes, with -1LL that is true, did not see that. Still hole remains, but in a new, and less likely, place such as SET_ERROR_BIT(-0x100000000) as the (uint32_t) cast simply wraps the negative values and then some will end up as 0-63.

    – chux
    Nov 26 '18 at 14:57





    Yes, with -1LL that is true, did not see that. Still hole remains, but in a new, and less likely, place such as SET_ERROR_BIT(-0x100000000) as the (uint32_t) cast simply wraps the negative values and then some will end up as 0-63.

    – chux
    Nov 26 '18 at 14:57













    0














    Problem:




    In the macros, you distinguish two cases, which, on their own, are okay. The warning comes from the branch that isn't executed, where the shift is out of range. (Apparently these diagnostics are issued before the dead branch is eliminated.)
    @M Oehm




    Solution



    Insure shifts are in range 0-31 in both paths regardless of the x value and type of x.



    x & 31 is a stronger insurance than x%32 or x%32u. % can result in negative remainders when x < 0 and with a wide enough type.



       #define SET_ERROR_BIT(x) do{
    if((x) < 0 || (x) >63){
    break;
    }
    if(((uint32_t)x)<32U){
    (error_field |= ((uint32_t)1U << ( (x)&31 )));
    break;
    } else if(((uint32_t)x)<64U){
    (error_field2 |= ((uint32_t)1U<<( (x)&31 )));
    }
    }while(0)




    As a general rule: good to use () around each usage of x.






    share|improve this answer






























      0














      Problem:




      In the macros, you distinguish two cases, which, on their own, are okay. The warning comes from the branch that isn't executed, where the shift is out of range. (Apparently these diagnostics are issued before the dead branch is eliminated.)
      @M Oehm




      Solution



      Insure shifts are in range 0-31 in both paths regardless of the x value and type of x.



      x & 31 is a stronger insurance than x%32 or x%32u. % can result in negative remainders when x < 0 and with a wide enough type.



         #define SET_ERROR_BIT(x) do{
      if((x) < 0 || (x) >63){
      break;
      }
      if(((uint32_t)x)<32U){
      (error_field |= ((uint32_t)1U << ( (x)&31 )));
      break;
      } else if(((uint32_t)x)<64U){
      (error_field2 |= ((uint32_t)1U<<( (x)&31 )));
      }
      }while(0)




      As a general rule: good to use () around each usage of x.






      share|improve this answer




























        0












        0








        0







        Problem:




        In the macros, you distinguish two cases, which, on their own, are okay. The warning comes from the branch that isn't executed, where the shift is out of range. (Apparently these diagnostics are issued before the dead branch is eliminated.)
        @M Oehm




        Solution



        Insure shifts are in range 0-31 in both paths regardless of the x value and type of x.



        x & 31 is a stronger insurance than x%32 or x%32u. % can result in negative remainders when x < 0 and with a wide enough type.



           #define SET_ERROR_BIT(x) do{
        if((x) < 0 || (x) >63){
        break;
        }
        if(((uint32_t)x)<32U){
        (error_field |= ((uint32_t)1U << ( (x)&31 )));
        break;
        } else if(((uint32_t)x)<64U){
        (error_field2 |= ((uint32_t)1U<<( (x)&31 )));
        }
        }while(0)




        As a general rule: good to use () around each usage of x.






        share|improve this answer















        Problem:




        In the macros, you distinguish two cases, which, on their own, are okay. The warning comes from the branch that isn't executed, where the shift is out of range. (Apparently these diagnostics are issued before the dead branch is eliminated.)
        @M Oehm




        Solution



        Insure shifts are in range 0-31 in both paths regardless of the x value and type of x.



        x & 31 is a stronger insurance than x%32 or x%32u. % can result in negative remainders when x < 0 and with a wide enough type.



           #define SET_ERROR_BIT(x) do{
        if((x) < 0 || (x) >63){
        break;
        }
        if(((uint32_t)x)<32U){
        (error_field |= ((uint32_t)1U << ( (x)&31 )));
        break;
        } else if(((uint32_t)x)<64U){
        (error_field2 |= ((uint32_t)1U<<( (x)&31 )));
        }
        }while(0)




        As a general rule: good to use () around each usage of x.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 26 '18 at 14:18

























        answered Nov 26 '18 at 13:47









        chuxchux

        84.8k874157




        84.8k874157























            0














            Seeing the thread I wanted to indicate a nice (and perhaps cleaner) way to set, reset and toggle the status of a bit in the case of the two unsigned integers as in thread. This code should be OT because uses x that shall be an unsigned int (or an int) and not a enum value.



            I've written the line of code at the end of this answer.



            The code receives as input a number of parameter couples. Each couple of parameter is a letter and a number. The letter may be:




            • S to set a bit

            • R to reset a bit

            • T to toggle a bit


            The number has to be a bit value from 0 to 63. The macros in the code discard each number greater than 63 and nothing is modified into the variables. The negative values haven't been evalued because we suppose a bit value is an unsigned value.



            For Example (if we name the program bitman):



            Executing: bitman S 0 S 1 T 7 S 64 T 7 S 2 T 80 R 1 S 63 S 32 R 63 T 62



            The output will be:



            S 0 00000000-00000001

            S 1 00000000-00000003

            T 7 00000000-00000083

            S 64 00000000-00000083

            T 7 00000000-00000003

            S 2 00000000-00000007

            T 80 00000000-00000007

            R 1 00000000-00000005

            S 63 80000000-00000005

            S 32 80000001-00000005

            R 63 00000001-00000005

            T 62 40000001-00000005



            #include <unistd.h>
            #include <stdio.h>
            #include <stdint.h>
            #include <string.h>

            static uint32_t err1 = 0;
            static uint32_t err2 = 0;

            #define SET_ERROR_BIT(x) (
            ((unsigned)(x)>63)?err1=err1:((x)<32)?
            (err1 |= (1U<<(x))):
            (err2 |= (1U<<((x)-32)))
            )

            #define RESET_ERROR_BIT(x) (
            ((unsigned)(x)>63)?err1=err1:((x)<32)?
            (err1 &= ~(1U<<(x))):
            (err2 &= ~(1U<<((x)-32)))
            )

            #define TOGGLE_ERROR_BIT(x) (
            ((unsigned)(x)>63)?err1=err1:((x)<32)?
            (err1 ^= (1U<<(x))):
            (err2 ^= (1U<<((x)-32)))
            )

            int main(int argc, char *argv)
            {
            int i;
            unsigned int x;

            for(i=1;i<argc;i+=2) {
            x=strtoul(argv[i+1],NULL,0);

            switch (argv[i][0]) {
            case 'S':
            SET_ERROR_BIT(x);
            break;
            case 'T':
            TOGGLE_ERROR_BIT(x);
            break;
            case 'R':
            RESET_ERROR_BIT(x);
            break;
            default:
            break;
            }

            printf("%c %2d %08X-%08Xn",argv[i][0], x, err2, err1);
            }

            return 0;
            }


            The macros are splitted in more then one line, but they are each a one-line code.



            The code main has no error control then if the parameters are not correctly specified the program might be undefined behaviour.






            share|improve this answer


























            • OP's code handled x < 0. This answer, like first one, has vulnerability when x < 0.

              – chux
              Nov 26 '18 at 13:32











            • It's not a vulnerability to avoid the x<0 control, because the input variable should be considered an unsigned at compilation time. If you use an int the code will be compiled with error. If you force the variable at a negative value the code will consider the value as a number greater or equal to 0, so it is sufficient to consider the control on greater than 63.

              – Sir Jo Black
              Nov 26 '18 at 13:37








            • 1





              Disagree with "because the input variable should be considered an unsigned at compilation time". Enumerated values are not certainly unsigned ref and OP wisely wants to prevent possibility with if(x < 0

              – chux
              Nov 26 '18 at 13:42











            • In the code I've implemented the variable x is an unsigned. May be I'm OT.

              – Sir Jo Black
              Nov 26 '18 at 13:46











            • @Chux, I understood your point of view :)

              – Sir Jo Black
              Nov 26 '18 at 13:50
















            0














            Seeing the thread I wanted to indicate a nice (and perhaps cleaner) way to set, reset and toggle the status of a bit in the case of the two unsigned integers as in thread. This code should be OT because uses x that shall be an unsigned int (or an int) and not a enum value.



            I've written the line of code at the end of this answer.



            The code receives as input a number of parameter couples. Each couple of parameter is a letter and a number. The letter may be:




            • S to set a bit

            • R to reset a bit

            • T to toggle a bit


            The number has to be a bit value from 0 to 63. The macros in the code discard each number greater than 63 and nothing is modified into the variables. The negative values haven't been evalued because we suppose a bit value is an unsigned value.



            For Example (if we name the program bitman):



            Executing: bitman S 0 S 1 T 7 S 64 T 7 S 2 T 80 R 1 S 63 S 32 R 63 T 62



            The output will be:



            S 0 00000000-00000001

            S 1 00000000-00000003

            T 7 00000000-00000083

            S 64 00000000-00000083

            T 7 00000000-00000003

            S 2 00000000-00000007

            T 80 00000000-00000007

            R 1 00000000-00000005

            S 63 80000000-00000005

            S 32 80000001-00000005

            R 63 00000001-00000005

            T 62 40000001-00000005



            #include <unistd.h>
            #include <stdio.h>
            #include <stdint.h>
            #include <string.h>

            static uint32_t err1 = 0;
            static uint32_t err2 = 0;

            #define SET_ERROR_BIT(x) (
            ((unsigned)(x)>63)?err1=err1:((x)<32)?
            (err1 |= (1U<<(x))):
            (err2 |= (1U<<((x)-32)))
            )

            #define RESET_ERROR_BIT(x) (
            ((unsigned)(x)>63)?err1=err1:((x)<32)?
            (err1 &= ~(1U<<(x))):
            (err2 &= ~(1U<<((x)-32)))
            )

            #define TOGGLE_ERROR_BIT(x) (
            ((unsigned)(x)>63)?err1=err1:((x)<32)?
            (err1 ^= (1U<<(x))):
            (err2 ^= (1U<<((x)-32)))
            )

            int main(int argc, char *argv)
            {
            int i;
            unsigned int x;

            for(i=1;i<argc;i+=2) {
            x=strtoul(argv[i+1],NULL,0);

            switch (argv[i][0]) {
            case 'S':
            SET_ERROR_BIT(x);
            break;
            case 'T':
            TOGGLE_ERROR_BIT(x);
            break;
            case 'R':
            RESET_ERROR_BIT(x);
            break;
            default:
            break;
            }

            printf("%c %2d %08X-%08Xn",argv[i][0], x, err2, err1);
            }

            return 0;
            }


            The macros are splitted in more then one line, but they are each a one-line code.



            The code main has no error control then if the parameters are not correctly specified the program might be undefined behaviour.






            share|improve this answer


























            • OP's code handled x < 0. This answer, like first one, has vulnerability when x < 0.

              – chux
              Nov 26 '18 at 13:32











            • It's not a vulnerability to avoid the x<0 control, because the input variable should be considered an unsigned at compilation time. If you use an int the code will be compiled with error. If you force the variable at a negative value the code will consider the value as a number greater or equal to 0, so it is sufficient to consider the control on greater than 63.

              – Sir Jo Black
              Nov 26 '18 at 13:37








            • 1





              Disagree with "because the input variable should be considered an unsigned at compilation time". Enumerated values are not certainly unsigned ref and OP wisely wants to prevent possibility with if(x < 0

              – chux
              Nov 26 '18 at 13:42











            • In the code I've implemented the variable x is an unsigned. May be I'm OT.

              – Sir Jo Black
              Nov 26 '18 at 13:46











            • @Chux, I understood your point of view :)

              – Sir Jo Black
              Nov 26 '18 at 13:50














            0












            0








            0







            Seeing the thread I wanted to indicate a nice (and perhaps cleaner) way to set, reset and toggle the status of a bit in the case of the two unsigned integers as in thread. This code should be OT because uses x that shall be an unsigned int (or an int) and not a enum value.



            I've written the line of code at the end of this answer.



            The code receives as input a number of parameter couples. Each couple of parameter is a letter and a number. The letter may be:




            • S to set a bit

            • R to reset a bit

            • T to toggle a bit


            The number has to be a bit value from 0 to 63. The macros in the code discard each number greater than 63 and nothing is modified into the variables. The negative values haven't been evalued because we suppose a bit value is an unsigned value.



            For Example (if we name the program bitman):



            Executing: bitman S 0 S 1 T 7 S 64 T 7 S 2 T 80 R 1 S 63 S 32 R 63 T 62



            The output will be:



            S 0 00000000-00000001

            S 1 00000000-00000003

            T 7 00000000-00000083

            S 64 00000000-00000083

            T 7 00000000-00000003

            S 2 00000000-00000007

            T 80 00000000-00000007

            R 1 00000000-00000005

            S 63 80000000-00000005

            S 32 80000001-00000005

            R 63 00000001-00000005

            T 62 40000001-00000005



            #include <unistd.h>
            #include <stdio.h>
            #include <stdint.h>
            #include <string.h>

            static uint32_t err1 = 0;
            static uint32_t err2 = 0;

            #define SET_ERROR_BIT(x) (
            ((unsigned)(x)>63)?err1=err1:((x)<32)?
            (err1 |= (1U<<(x))):
            (err2 |= (1U<<((x)-32)))
            )

            #define RESET_ERROR_BIT(x) (
            ((unsigned)(x)>63)?err1=err1:((x)<32)?
            (err1 &= ~(1U<<(x))):
            (err2 &= ~(1U<<((x)-32)))
            )

            #define TOGGLE_ERROR_BIT(x) (
            ((unsigned)(x)>63)?err1=err1:((x)<32)?
            (err1 ^= (1U<<(x))):
            (err2 ^= (1U<<((x)-32)))
            )

            int main(int argc, char *argv)
            {
            int i;
            unsigned int x;

            for(i=1;i<argc;i+=2) {
            x=strtoul(argv[i+1],NULL,0);

            switch (argv[i][0]) {
            case 'S':
            SET_ERROR_BIT(x);
            break;
            case 'T':
            TOGGLE_ERROR_BIT(x);
            break;
            case 'R':
            RESET_ERROR_BIT(x);
            break;
            default:
            break;
            }

            printf("%c %2d %08X-%08Xn",argv[i][0], x, err2, err1);
            }

            return 0;
            }


            The macros are splitted in more then one line, but they are each a one-line code.



            The code main has no error control then if the parameters are not correctly specified the program might be undefined behaviour.






            share|improve this answer















            Seeing the thread I wanted to indicate a nice (and perhaps cleaner) way to set, reset and toggle the status of a bit in the case of the two unsigned integers as in thread. This code should be OT because uses x that shall be an unsigned int (or an int) and not a enum value.



            I've written the line of code at the end of this answer.



            The code receives as input a number of parameter couples. Each couple of parameter is a letter and a number. The letter may be:




            • S to set a bit

            • R to reset a bit

            • T to toggle a bit


            The number has to be a bit value from 0 to 63. The macros in the code discard each number greater than 63 and nothing is modified into the variables. The negative values haven't been evalued because we suppose a bit value is an unsigned value.



            For Example (if we name the program bitman):



            Executing: bitman S 0 S 1 T 7 S 64 T 7 S 2 T 80 R 1 S 63 S 32 R 63 T 62



            The output will be:



            S 0 00000000-00000001

            S 1 00000000-00000003

            T 7 00000000-00000083

            S 64 00000000-00000083

            T 7 00000000-00000003

            S 2 00000000-00000007

            T 80 00000000-00000007

            R 1 00000000-00000005

            S 63 80000000-00000005

            S 32 80000001-00000005

            R 63 00000001-00000005

            T 62 40000001-00000005



            #include <unistd.h>
            #include <stdio.h>
            #include <stdint.h>
            #include <string.h>

            static uint32_t err1 = 0;
            static uint32_t err2 = 0;

            #define SET_ERROR_BIT(x) (
            ((unsigned)(x)>63)?err1=err1:((x)<32)?
            (err1 |= (1U<<(x))):
            (err2 |= (1U<<((x)-32)))
            )

            #define RESET_ERROR_BIT(x) (
            ((unsigned)(x)>63)?err1=err1:((x)<32)?
            (err1 &= ~(1U<<(x))):
            (err2 &= ~(1U<<((x)-32)))
            )

            #define TOGGLE_ERROR_BIT(x) (
            ((unsigned)(x)>63)?err1=err1:((x)<32)?
            (err1 ^= (1U<<(x))):
            (err2 ^= (1U<<((x)-32)))
            )

            int main(int argc, char *argv)
            {
            int i;
            unsigned int x;

            for(i=1;i<argc;i+=2) {
            x=strtoul(argv[i+1],NULL,0);

            switch (argv[i][0]) {
            case 'S':
            SET_ERROR_BIT(x);
            break;
            case 'T':
            TOGGLE_ERROR_BIT(x);
            break;
            case 'R':
            RESET_ERROR_BIT(x);
            break;
            default:
            break;
            }

            printf("%c %2d %08X-%08Xn",argv[i][0], x, err2, err1);
            }

            return 0;
            }


            The macros are splitted in more then one line, but they are each a one-line code.



            The code main has no error control then if the parameters are not correctly specified the program might be undefined behaviour.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 26 '18 at 14:59

























            answered Nov 26 '18 at 13:28









            Sir Jo BlackSir Jo Black

            1,291918




            1,291918













            • OP's code handled x < 0. This answer, like first one, has vulnerability when x < 0.

              – chux
              Nov 26 '18 at 13:32











            • It's not a vulnerability to avoid the x<0 control, because the input variable should be considered an unsigned at compilation time. If you use an int the code will be compiled with error. If you force the variable at a negative value the code will consider the value as a number greater or equal to 0, so it is sufficient to consider the control on greater than 63.

              – Sir Jo Black
              Nov 26 '18 at 13:37








            • 1





              Disagree with "because the input variable should be considered an unsigned at compilation time". Enumerated values are not certainly unsigned ref and OP wisely wants to prevent possibility with if(x < 0

              – chux
              Nov 26 '18 at 13:42











            • In the code I've implemented the variable x is an unsigned. May be I'm OT.

              – Sir Jo Black
              Nov 26 '18 at 13:46











            • @Chux, I understood your point of view :)

              – Sir Jo Black
              Nov 26 '18 at 13:50



















            • OP's code handled x < 0. This answer, like first one, has vulnerability when x < 0.

              – chux
              Nov 26 '18 at 13:32











            • It's not a vulnerability to avoid the x<0 control, because the input variable should be considered an unsigned at compilation time. If you use an int the code will be compiled with error. If you force the variable at a negative value the code will consider the value as a number greater or equal to 0, so it is sufficient to consider the control on greater than 63.

              – Sir Jo Black
              Nov 26 '18 at 13:37








            • 1





              Disagree with "because the input variable should be considered an unsigned at compilation time". Enumerated values are not certainly unsigned ref and OP wisely wants to prevent possibility with if(x < 0

              – chux
              Nov 26 '18 at 13:42











            • In the code I've implemented the variable x is an unsigned. May be I'm OT.

              – Sir Jo Black
              Nov 26 '18 at 13:46











            • @Chux, I understood your point of view :)

              – Sir Jo Black
              Nov 26 '18 at 13:50

















            OP's code handled x < 0. This answer, like first one, has vulnerability when x < 0.

            – chux
            Nov 26 '18 at 13:32





            OP's code handled x < 0. This answer, like first one, has vulnerability when x < 0.

            – chux
            Nov 26 '18 at 13:32













            It's not a vulnerability to avoid the x<0 control, because the input variable should be considered an unsigned at compilation time. If you use an int the code will be compiled with error. If you force the variable at a negative value the code will consider the value as a number greater or equal to 0, so it is sufficient to consider the control on greater than 63.

            – Sir Jo Black
            Nov 26 '18 at 13:37







            It's not a vulnerability to avoid the x<0 control, because the input variable should be considered an unsigned at compilation time. If you use an int the code will be compiled with error. If you force the variable at a negative value the code will consider the value as a number greater or equal to 0, so it is sufficient to consider the control on greater than 63.

            – Sir Jo Black
            Nov 26 '18 at 13:37






            1




            1





            Disagree with "because the input variable should be considered an unsigned at compilation time". Enumerated values are not certainly unsigned ref and OP wisely wants to prevent possibility with if(x < 0

            – chux
            Nov 26 '18 at 13:42





            Disagree with "because the input variable should be considered an unsigned at compilation time". Enumerated values are not certainly unsigned ref and OP wisely wants to prevent possibility with if(x < 0

            – chux
            Nov 26 '18 at 13:42













            In the code I've implemented the variable x is an unsigned. May be I'm OT.

            – Sir Jo Black
            Nov 26 '18 at 13:46





            In the code I've implemented the variable x is an unsigned. May be I'm OT.

            – Sir Jo Black
            Nov 26 '18 at 13:46













            @Chux, I understood your point of view :)

            – Sir Jo Black
            Nov 26 '18 at 13:50





            @Chux, I understood your point of view :)

            – Sir Jo Black
            Nov 26 '18 at 13:50


















            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.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53479744%2fleft-shift-count-width-of-type-in-c-macro%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

            Tonle Sap (See)

            I get strange results when I access the Sqlitedatabase with Unity C# via XAMPP

            Guatemaltekische Davis-Cup-Mannschaft