Search code examples
cvariableszerolocal-variables

Variable receiving 0x00 every time regardless of variable


This is a simple C file I'm using. Essentially, I am looking to test each ASCII character to see if they are polar opposites (such 0x5b5b5b5b and 0x24242424 where 5b nad 24 are ASCII).

#include <stdio.h>
#define SHOW 0

int main(){
    char c = '\x00';
    int i = 100;
    long long var1 = 0x5b5b5b5b;
    long long var2 = 0x24242424;
    printf("%d - %d - %d\n", i, var1, var2);
    i &= var1;
    printf("%d - %d - %d\n", i, var1, var2);
    i &= var2;
    printf("%d - %d - %d\n", i, var1, var2);

    /*
     * If they want to actually list them all, keep SHOW = 1
     */
    if(SHOW)
        for(c = '\x20'; c < 0x7E; c++)
            if(~c - 0xffffff00 - 0x80 > 0x20 && ~c - 0xffffff00 - 0x80 <= 0x7e)
                printf("AND reg, %x\nAND reg, %x\n\n", c, (~c - 0xffffff00 - 0x80));
    /*
     * If they want to test var1 and var2
     */
    if(!SHOW)
        if(i==0)
            printf("0x%x and 0x%x are opposites!\n", var1, var1);
    //Why does the second one return 0 every time?
}

I have some debugging printf's and the error stands that var2 is not being populated. I have changed its value to no avail. Why is it not getting assigned a value?


Solution

  • Representation of types is machine-dependent. Based on the behavior on your machine you seem to be describing, a long long will probably receive twice the memory space a long receives, and your machine uses little-endian number representation.   

    When you call printf, the arguments are pushed in inverse order on the stack (memory order higher to lower usually; allocation in bytes assumed/how it would be, eg, on my (old) machine):

    mem allocated     long(int)    long long
    
         arg2            4             8
         arg1            4             8
      fmt string         x             x   
    

    where x is the byte size of your format string. As you print a long long variable (say, 8 bytes) and later a long one (say, 4 bytes) with the format specifiers of an int (%d), and this works fine for the long case, longs and ints probably have the same byte width on your machine.   

    As it doesn't for long longs, they are probably twice as wide, as hypothesized above. When you look at the stack above, this means that in case of pushing 2 long longs, but using a %d specifier, printf assumes the first 4 bytes after the fmt string are the first argument, and the next 4 bytes are the second argument. However, these 8 bytes actually comprise the first long long argument. In little-endian notation, the first 4 bytes are its lower order bytes, which coincide with your first variable - so arg 1 is printed fine. The next 4 bytes will be the higher order bytes - all 0, so printf prints always 0 for your second variable. As it should.   

    Read up on format specifiers: use %d, %ld, etc, as appropriate; and always compile with warnings as your compiler would have given you a hint what's wrong by emitting a warning (-Wall with gcc).