Weird behavior on Macro...

This is a discussion on Weird behavior on Macro... within the C Programming forums, part of the General Programming Boards category; Hi, i have a code where i defined: #define FULLMASK 0xFFFFFFFF #define BITMASK(x) (~(FULLMASK<<x)) If i use an uint8_t variable ...

  1. #1
    Registered User
    Join Date
    Oct 2010
    Posts
    16

    Weird behavior on Macro...

    Hi, i have a code where i defined:

    #define FULLMASK 0xFFFFFFFF
    #define BITMASK(x) (~(FULLMASK<<x))

    If i use an uint8_t variable with value 32 the macro returns 0, but if i write BITMASK(32) the macro returns 0XFFFFFFFF (that is the value that i was expecting).
    Any idea why thats happening? I am using Mingw32 with Code Blocks on Windows...

    Thank you!

  2. #2
    Registered User
    Join Date
    May 2010
    Location
    Naypyidaw
    Posts
    1,314
    Nothing to do with macro. Data-Type Conversions
    0xFFFFFFFF may not fit in int, btw.
    Last edited by Bayint Naung; 06-13-2011 at 08:51 AM.

  3. #3
    Registered User
    Join Date
    Oct 2010
    Posts
    16
    Could not get the point..

    What is the difference of

    uint8_t val = 32;
    uint32_t ret;

    ret = BITMASK(val); //return 0
    ret = BITMASK(32); // return 0xFFFFFFFF

  4. #4
    Registered User
    Join Date
    May 2009
    Posts
    2,585
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    
    #define FULLMASK 0xFFFFFFFFUL
    #define BITMASK(x) (~(FULLMASK<<(unsigned long)(x)))
    
    int main()
    {
        uint8_t val = 32;
        uint32_t ret;
    
        ret = BITMASK(val); //return 0xFFFFFFFF
        printf("ret: %X\n", ret);
        ret = BITMASK(32); // return 0xFFFFFFFF
        printf("ret: %X\n", ret);
    
        return 0;
    }
    You need to make sure the data type is right.

    Tim S.

  5. #5
    Registered User
    Join Date
    Oct 2010
    Posts
    16
    Nop it does not work.. i did copy and paste your code and got same result... do you think thats some problem with my mingw? Anyway i cant understand why should i have this behavior x is just the shift argument.. but the main argumen is still 0xFFFFFFFF that is a 32 bits variable.. and anyway.. for any argument.. an ~should return a non-zero value...

  6. #6
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,558
    Weird, or just undefined.
    Quote Originally Posted by Draft C99
    6.5.7 Bitwise shift operators
    Syntax
    1
    shift-expression:
    additive-expression
    shift-expression << additive-expression
    shift-expression >> additive-expression
    Constraints
    2
    Each of the operands shall have integer type.
    Semantics
    3
    The integer promotions are performed on each of the operands. The type of the result is
    that of the promoted left operand. If the value of the right operand is negative or is
    greater than or equal to the width of the promoted left operand, the behavior is undefined.
    The first thing, since you're using MinGW (which is a GCC port) is turn up the warning level, and perhaps pay attention to them (if you're already seeing them).
    For example
    $ gcc -S baz.c
    baz.c: In function ‘main’:
    baz.c:15: warning: left shift count >= width of type


    The second is that with the known constant, the compiler just works out an answer, and in the case with a variable, it actually generates a bunch of code.
    Code:
    ;    ret = BITMASK(val); //return 0xFFFFFFFF
    ;    printf("ret: %X\n", ret);
    	movb	$32, 31(%esp)
    	movzbl	31(%esp), %eax
    	movl	$-1, %edx
    	movl	%edx, %ebx
    	movl	%eax, %ecx
    	sall	%cl, %ebx
    	movl	%ebx, %eax
    	notl	%eax
    	movl	%eax, 24(%esp)
    	movl	$.LC0, %eax
    	movl	24(%esp), %edx
    	movl	%edx, 4(%esp)
    	movl	%eax, (%esp)
    	call	printf
    
    ;    ret = BITMASK(32); // return 0xFFFFFFFF
    ;    printf("ret: %X\n", ret);
    	movl	$-1, 24(%esp)
    	movl	$.LC0, %eax
    	movl	24(%esp), %edx
    	movl	%edx, 4(%esp)
    	movl	%eax, (%esp)
    	call	printf
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  7. #7
    Registered User
    Join Date
    Oct 2010
    Posts
    16
    Oh ok thats explain everything now.. yea i was getting that warning but i was ignoring the equal case.. so i cant shift a 32bits variable 32 times...

    using 0x1FFFFFFFF works but i dont know if thats the best workaround...

  8. #8
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    611
    That's the language reason, the x86 technical reason is:
    Quote Originally Posted by IA32 Dev Manual - Vol. 2b SAL/SAR/SHL/SHR
    The 8086 does not mask the shift count. However, all other IA-32 processors (starting with the
    Intel 286 processor) do mask the shift count to 5 bits, resulting in a maximum count of 31.
    Code:
    uint8_t val = 32;
    ret = BITMASK(val); // 0?
    ret = (~(0xFFFFFFFF << (32 & 31))
    ret = (~(0xFFFFFFFF << 0))
    ret = (~(0xFFFFFFFF))
    ret = 0

  9. #9
    Registered User
    Join Date
    Oct 2010
    Posts
    16
    So why it does work with 0x1FFFFFFFF?

    And why BITMASK(32) works?

    the 32 is suposed to be masked by the 5 bits too no?

  10. #10
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,498
    When you add that 1 in front of all those F's, you make your literal value bigger than what fits in a 32-bit number. Your compiler is treating it as a 64-bit number, thus shifting 32 positions is fine, since 32 is less than the width of the promoted operand. If you want a 32-bit mask, use a 32-bit literal (0xFFFFFFFFU), and only shift at most 31 positions. Also, it's a good idea to put a U after the literal to ensure it's treated as an unsigned value. The << and >> operators can result in undefined behavior when shifting signed ints.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. cygwin sshd weird behavior
    By jEssYcAt in forum Tech Board
    Replies: 6
    Last Post: 05-19-2008, 02:05 PM
  2. Weird cin behavior
    By Link_26 in forum C++ Programming
    Replies: 4
    Last Post: 06-25-2006, 09:25 PM
  3. really weird behavior, 16 bit asm w/masm
    By BobMcGee123 in forum A Brief History of Cprogramming.com
    Replies: 7
    Last Post: 12-01-2005, 05:45 PM
  4. Weird computer behavior
    By ober in forum Tech Board
    Replies: 14
    Last Post: 03-08-2005, 11:26 AM
  5. Weird Excel behavior
    By Govtcheez in forum Tech Board
    Replies: 1
    Last Post: 12-03-2004, 12:53 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21