tags:

views:

384

answers:

5

Hi. As of what I know about '&' operator, it returns the base address of the operand in memory.

Let us imagine the following scenario (as on my machine):

  • sizeof(int) = 4 bytes
  • sizeof(float) = 4 bytes
  • sizeof(char) = 1 byte

Now, if I write something like this:

void main() {
 int i = 5411;
 int *ip = &i;
 char *c = &i;

 printf("%d",*ip);
 printf("%c",*c);
}

The first printf() should give me 5411. Talking about the second printf(), the base address of i contains 10101001 (higher order 8 bits = 1 byte for char type pointer). Hence *c should give me 169, which when converted to %c is an invalid character.

But the compiler is giving me '#' or some other valid output. Why is it so ? Any inputs ?

EDIT (taken from the author's comment on one of the answers):

That was just a dummy case, since I was away from the actual machine.
The actual case is i = 5411

+5  A: 

ASCII only defines characters up to 127. Besides that, what you really want to do is print the numeric corresponding to the value in *c, this is also done using %d...

 printf("%d",*c);

...should display the number as you expect.

Mark E
That was just a dummy case, since I was away from the actual machine. The actual case is i = 5411. %c gives '#' and %d gives 35 (instead of 169)
Gaurav Kalra
@Guarav: ASCII still only defines characters up to 127, and what you really seem to want is to print numbers, so print numbers, not characters.
Mark E
@Gaurav -- Why are you expecting 169? On a little endian machine, it should be 35. On a big endian machine, it should be 0.
PigBen
-1 for "extended ASCII" instead of specifying a character encoding. There is no such thing as "extended ASCII".
R..
+1  A: 

The Address of *c is that of i, because you have assigned c to &i. It will then take the highest or lowest (depends on the endian) and print that character.

Alexander Rafferty
The case of i = 5411 is printing '#' as the character. An ASCII of 35 (10101001), which is neither the upper 8 nor lower 8 bits.
Gaurav Kalra
@Gaurav -- 35 in binary is 00100011
PigBen
Agreed. There won't be a truncation with the *c because the character pointer is large enough to hold the entire value of the memory location.
Sam Hoice
@Gaurav Kalra: Why are you saying it was `1154` in your original post, and the saying it was `5411` in the comments? `1154` and `5411` are two different numbers, if you noticed.
AndreyT
Am sorry for that: That was just a dummy case, since I was away from the actual machine.
Gaurav Kalra
+23  A: 

You seems to have trouble understanding how integers are stored in memory. Take 5411 as example.

5411 = 1010100100011

this number 13 binary digits has however, since an int is 32-bit, it must be pad to 32 digits

5411 = 00000000 00000000 00010101 00100011

On a little endian machine (x86, ARM by default), the least significant bytes are stored in the front, so in the memory:

00100011   00010101    00000000    00000000
^
c          c + 1       c + 2       c + 3
ip

Therefore, *c should return 00100011 i.e. 35 ('#').

KennyTM
Hey thanks a lot!! This is exactly what I was looking for :-)
Gaurav Kalra
Where did `5411` come from? The OP's code clearly initializes `i` with `1154`.
AndreyT
@AndreyT: See OP's comments on other answers.
KennyTM
Someone with question editing privileges should edit the question.
PigBen
@PigBen: Okay, I did that. Sorry for creating little confusion
Gaurav Kalra
+1  A: 

Just to learn something about the encoding of your integers you should experiment a bit and do

printf("0x%X, %X|%X|%X|%X\n", 
  i, 
  i & 0xFF,
  (i >> 8) & 0xFF
  (i >> 16) & 0xFF
  (i >> 24) & 0xFF
  );

An then do the same with c[0], c[1] etc and other format strings as %c.

Jens Gustedt
+3  A: 

Firstly, your program is ill-formed. Neither C nor C++ allows initializing an char * pointer with an int * value. You need an explicit cast in your initialization of c pointer.

Secondly, which byte of the original integer i - higher order or lower order - resides at its "base address" is implementation-defined. There are little-endian architectures, where the lower-order but will be seen through *c (which is has value 130 on a 8-bit char machine, not 114). And there are big-endian architectures, where the higher-order but will be seen through *c (which is 0 on a 8-bit char machine). So you should expect either character with code 130 or character with code 0 to be printed with %c format specifier.

Thirdly, in a typical implementation there's normally no such thing as "invalid character code". For any code something will usually be printed in one way or the other. I don't see though how you managed to obtain # as the output from your code. Is this the real code you were running?

AndreyT
Hi Andrey. 1-> The code is compiling. Should I care for explicit casting then? ... 2-> Yeah, I was not aware of this, which KennyTM answered ... 3-> I mentioned, it's a dummy code
Gaurav Kalra
@Gaurav Kalra: Compiling as what? You tagged you question [C] and [C++]. This code will not compile as C++ by any self-respecting C++ compiler. C compilers with overly relaxed error checking might allow that (with a warning), but the code is still illegal even as C, so if you care about writing valid C code the cast is required.
AndreyT