Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

a == p will also resolve to true. So will c == p. a and b don't add anything to your example; they're just in there to make c and p look like they're more different than they are.

    $ cat zero.c
    #include "stdio.h"

    int main(int argc, char* argv[]) {
     char nul = 0;
     void* null = 0;

     if( nul == null ) {
      printf("compared char to pointer; they are the same\n");
     } else {
      printf("found a difference between char and pointer\n");
     }
     return 0;
    }

    $ gcc -o zero zero.c
    zero.c: In function ‘main’:
    zero.c:7:10: warning: comparison between pointer and integer
      if( nul == null ) {
              ^~
    $ ./zero
    compared char to pointer; they are the same
    $
You get a warning, but not an error, for making the comparison. By contrast, assigning the integer zero to a void* isn't even a warning -- it's just a natural thing to do. There isn't another way to set a pointer to NULL. There is another way to set a character to 0, the '\0' syntax, but that's not a warning either.

C will think nothing of adding '!' to 'P' and getting 'q'. That's not strange because addition is a pretty normal thing to do with integers. You're right that a char variable should only occupy 8 bits of memory, but that's an implementation artifact, not a theory of what the value '\0' means. That value is unambiguously the integer zero with infinite precision. The reason it only occupies 8 bits is that you can't let it have infinite bits.



Hmm. Probably true. What about c == p? I don't recall whether both will promote to numeric, or whether it's a type error.

For that matter, what does (uncasted) p = c do? How about c = p?

[Edit: You updated while I was writing; my first question you already answered. Warning, not error.]


    $ cat pointers.c 
    #include "stdio.h"

    int main(int argc, char* argv[]) {
     char Z = 'Z';
     char q = 'q';
     void* null = 0;

     printf("Z is \\x%02x\n", Z);
     printf("But if it were a pointer, it would be %08x\n", Z);
     printf("Watch this:\n\n");

     null = Z;

     /* %p to print a pointer value */
     printf("Our void* is now: %p\n", null);

     q = null;

     printf("And q is: %c\n", q);

     return 0;
    }
    $ gcc -o pointers pointers.c
    pointers.c: In function ‘main’:
    pointers.c:12:7: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
      null = Z;
           ^
    pointers.c:17:4: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
      q = null;
        ^
    $ ./pointers
    Z is \x5a
    But if it were a pointer, it would be 0000005a
    Watch this:

    Our void* is now:     0x5a
    And q is: Z
    $
The assignments are warnings. They work just like you'd expect them to work.

Notice all the different printf flags? This is why you need them.


The literal 0 in a pointer context will be converted to a NULL pointer, which can be a non-zero bit pattern (there are some systems where the actual NULL pointer isn't all zeros). Going through a variable might not do what you think. So this:

    char *p = 0;
is fine, but

    intptr_t a = 0;
    char *p = (char *)a;
might not do what you expect (set p to the NULL pointer).




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: