c - Dereferencing this pointer gives me -46, but I am not sure why -


this program ran:

#include <stdio.h>  int main() {     int y = 1234;     char *p = &y;     int *j  = &y;     printf("%d " , *p);     printf("%d" , *j); } 

i confused output. i'm seeing is:

-46 1234 

i wrote program experiment , wasn't sure going output. expecting possibly 1 byte y.

what happening "behind-the-scenes" here? how dereferencing p give me -46?

update
pointed out other had explicit casting not cause ub.i not changing line char *p = &y char *p = (char *)&y not invalidating below answers.

there couple of issues code written.

first of all, invoking undefined behavior trying print numeric representation of char object using %d conversion specifier:

online c 2011 draft, §7.21.6.1, subclause 9:

if conversion specification invalid, behavior undefined.282) if argument not correct type corresponding conversion specification, behavior undefined.

yes, objects of type char promoted int when passed variadic functions; printf special, , if want output well-defined, type of argument , conversion specifier must match up. print numeric value of char %d or unsigned char argument %u, %o, or %x, must use hh length modifier part of conversion spec:

printf( "%hhd ", *p ); 

the second issue line

char *p = &y; 

is constraint violation - char * , int * not compatible types, , may have different sizes and/or representations2. thus, must explicitly cast source target type:

char *p = (char *) &y; 

the one exception rule occurs when 1 of operands void *; cast isn't necessary.

having said that, took code , added utility dumps address , contents of objects in program. here's y, p, , j on system (sles-10, gcc 4.1.2):

       item        address   00   01   02   03        ----        -------   --   --   --   --           y 0x7fff1a7e99cc   d2   04   00   00    ....            p 0x7fff1a7e99c0   cc   99   7e   1a    ..~.             0x7fff1a7e99c4   ff   7f   00   00    ....            j 0x7fff1a7e99b8   cc   99   7e   1a    ..~.             0x7fff1a7e99bc   ff   7f   00   00    .... 

i'm on x86 system, little-endian, stores multi-byte objects starting least-significant byte @ lowest address:

be:        a+1  a+2  a+3        +----+----+----+----+     y: | 00 | 00 | 04 | d2 |        +----+----+----+----+ le:     a+3  a+2  a+1   

on little-endian system, addressed byte least-significant byte, in case 0xd2 (210 unsigned, -46 signed).

in nutshell, you're printing signed, decimal representation of single byte.

as broader question, type of expression *p char , type of expression *j int; compiler goes type of expression. compiler keeps track of objects, expressions, , types translates source machine code. when sees expression *j, knows it's dealing integer value , generates machine code appropriately. when sees expression *p, knows it's dealing char value.


  1. admittedly, modern desktop systems know of use same representations pointer types, more oddball embedded or special-purpose platforms, may not true.
  2. § 6.2.5, subclause 28.


Comments

Popular posts from this blog

c++ - llvm function pass ReplaceInstWithInst malloc -

java.lang.NoClassDefFoundError When Creating New Android Project -

Decoding a Python 2 `tempfile` with python-future -