5

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

7
  • In any case, if you try to "print" a "char" it will be displayed as a char, not as the corresponding integer code. Commented Oct 31, 2010 at 20:20
  • probably something to do with char encoding being used, I would guess. Commented Oct 31, 2010 at 20:21
  • Yeah I too agree with that. But there must be a reason for getting '#' value from the last printf(). It's not a garbage value. Commented Oct 31, 2010 at 20:23
  • 1
    Shouldn't it be 130 instead of 144? Commented Oct 31, 2010 at 20:24
  • 1
    @Gaurav Kalra: actually, there is no guarantee you will get 114 as a result. You are counting on endienness (en.wikipedia.org/wiki/Endianness) to get 144, but not all systems are little endian. Commented Oct 31, 2010 at 20:27

5 Answers 5

24

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 ('#').

Sign up to request clarification or add additional context in comments.

4 Comments

Where did 5411 come from? The OP's code clearly initializes i with 1154.
@AndreyT: See OP's comments on other answers.
Someone with question editing privileges should edit the question.
@PigBen: Okay, I did that. Sorry for creating little confusion
5

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.

4 Comments

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)
@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.
@Gaurav -- Why are you expecting 169? On a little endian machine, it should be 35. On a big endian machine, it should be 0.
-1 for "extended ASCII" instead of specifying a character encoding. There is no such thing as "extended ASCII".
3

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?

2 Comments

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: 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.
1

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.

5 Comments

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 -- 35 in binary is 00100011
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.
@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.
Am sorry for that: That was just a dummy case, since I was away from the actual machine.
1

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.