2

When I run this code:

int arr[3] = {2,3,4};
char *p;
p = (char*)arr;
printf("%d", *p);
p = p+1;
printf("%d", *p);

The output is 2 and 0. The second result is slightly confusing. Could someone explain why this is happening?

13
  • 3
    Is this a homework? If so - tag it accordingly. Commented Dec 31, 2011 at 11:08
  • 3
    What happened when you ran this code? Reasoning: before posting a question here, it's always a good idea to show us what you've tried and what the result was. Commented Dec 31, 2011 at 11:11
  • 1
    The output was 2 and 0. the second result was slightly confusing. Hence the question. I'm a cardiac surgeon, who's trying to help my son with his homework. Unfortunately god has not made all of us a C expert. Commented Dec 31, 2011 at 11:12
  • 1
    I just posted an answer, but your last comment makes me want to delete it. Don't make judgements about others. Commented Dec 31, 2011 at 11:27
  • 1
    @user1124236 we answer (and ask :D) lots and lots of simple questions on SO. However we especially like to answer questions which demonstrate some research effort of the asker. Commented Dec 31, 2011 at 11:27

5 Answers 5

9

Let's break this down:

int arr[3] = {2,3,4};

Creates an array of 3 integers. Assuming your system is 32bit little endian this is how it looks in memory:

02 00 00 00 03 00 00 00 04 00 00 00

char *p; p = (char*)arr;

p now points to arr but is a pointer to char*. In other words, p points to the 02.

printf("%d", *p);

You are printing as an int the location referenced by p. So when you dereference p (by writing *p) you are accessing the char (since p is of type char*) referenced by p. Which is 02.

p = p+1;

p now points to the 00 just after 02, because p is char*. So when you add 1, it will move by 1 * sizeof(char) = 1 * 1 = 1 byte in memory.

printf("%d", *p);

You are printing as an int the location referenced by p. So when you dereference p (by writing *p) you are accessing the char (since p is of type char*) referenced by p. Which is 00.

If you wanted to print 3 instead of 0 you have to change your pointer type to int* instead of char*, making the pointer move by 1 * sizeof(int) = 1 * 4 = 4 bytes in memory.

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

2 Comments

Let me also emphasize that while reading values of type int as if they were chars is legal, the exact result depends on the implementation. You could get another result when compiled elsewhere. @Cicada had to make assumptions about the platform in order to provide an answer.
assuming int is 32bit, it'd not matter if the platform is either 32 or 64bit (or even 16bit). on a flip note, pondering on endianness happened quite late for me, I used to assume only little endian type existed. coming from 6502, z80 and 8088 it was a surprise the numbers can be represented differently.
4

The result you get will depend on the size of int on your implementation and its endianness.

Assuming 32bit ints, 8bit chars and a litte-endian environment (say x86), arr will be like this in memory:

<  arr[0]  > <  arr[1]  > <  arr[2] >
02 00 00 00  03 00 00 00  04 00 00 00
^  ^         ^
p  p+1 ...   p+4

If you take a char pointer to the start of that memory, and print out the first element, 2 should be output. If you increment that pointer, 0 will be output next. You'll need to increment it a few times more to 'see' 3.

Note that on a big-endian environment with the same type sizes, your program would have output two zeros, because the layout would have been:

<  arr[0]  > <  arr[1]  > <  arr[2] >
00 00 00 02  00 00 00 03  00 00 00 04
^  ^         ^
p  p+1 ...   p+4

Comments

2

This is because of something called endianness.

When you create an array like int arr[3] = {2, 3, 4}; it gets created in the memory as follows

Big endian:
    0   1   2     3      4   5   6      7     8   9  10     11 
  +---+---+---+--------+---+---+---+--------+---+---+---+--------+
  |   |   |   | ..0010 |   |   |   | ..0011 |   |   |   | ..0100 |
  +---+---+---+--------+---+---+---+--------+---+---+---+--------+

  <--       2       --><--       3        --><--        4      -->

Little endian:
       0     1   2    3    4   5   6      7     8       9  10   11 
  +--------+---+---+---+---------+---+---+---+--------+---+---+---+
  | ..0010 |   |   |   |  ..0011 |   |   |   | ..0100 |   |   |   |
  +--------+---+---+---+---------+---+---+---+--------+---+---+---+

  <--       2       --><--       3        --><--        4      -->

To understand more, you need to modify you program as follows:

int main(void)
{

    int arr[3] = {2, 3, 4};
    char *p = (char*) arr;  
    int i;
    int size = (int)sizeof(arr);

    for (i=0; i<size ; i++) {
        printf("%d", *p);
        p++;
    }

    return 0;
}

And, to check the endianness of you hardware, you can use the following function.

void endian(void)
{
        int i = 1;

        if (*(char *) &i == 1)
                printf("Little endian \n");
        else
                printf("Big endian \n");

        return;
}

Comments

1

Here is a paste that will let you understand the issue better: http://codepad.org/ClrrwjKY

As you can see, the value of the consecutive integers appear separated by three zeroes. This is because an integer is 4 bytes long, whereas a char is only 1 byte long. So when the int array is cast to char, you iterate over it byte by byte (or char by char), not by four bytes (int by int).

Comments

0

Here as 'p' is a character pointer.. p+1 increments the current value of p only by 1. As the array is integer, in order to access each values of the array one by one, you'll have to increment the character array by 2. If the address of integer array is 1000 therefore,

  arr[0] is at 1000
  arr[1] is at 1002
  arr[2] is at 1004

and the value of arr is the address of arr[0]; so initially

 p=arr=1000

when p is incremented, p is 1001 whereas arr[1] is 1002

.. So in order to access all the values you'll have to increment the value of p twice each time..

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.