2
#include <stdio.h>
int main()
{
    int a[3]={2,3,4};
    char *p=a;
    printf("%d ",*p);

    p=(int *)(p+1);//What does this statement do ?
    printf("%d",*p); //Will the pointer extract 2 bytes(16 bit compiler)or1?  

    return 0;
}

I'm getting output as 2 0 . I understood why the first printf is printing 2 but not understanding why 0 in the next printf ? Is it that if I want to jump so many bytes away then I should a pointer of that many bytes long ?

7
  • 4
    Hint: think about what a[] looks like in memory. (Also note that you appear to be running this program on a little endian architecture). Commented Jun 22, 2016 at 16:48
  • 1
    p+1 increments p by as many bytes the type it points is long. Commented Jun 22, 2016 at 16:50
  • Another hint: consider doing a sizeof() for int and char Commented Jun 22, 2016 at 16:57
  • not understanding why 0 in the next printf What were you expecting to see? Commented Jun 22, 2016 at 16:58
  • 2
    p=(int *)(p+1); is undefined behavior (UB) as it can violate alignment requirements. Code may crash Commented Jun 22, 2016 at 18:02

4 Answers 4

3

p=(int *)(p+1); is a constraint violation, because int * may not be assigned to char *.

The compiler must issue a diagnostic message. The behaviour of any executable generated by a program with a constraint violation is undefined.

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

Comments

1

There's so much wrong in that code.

First of all, as pointed out in the answer by M.M, the code will not even compile without raising a diagnostic message from the compiler. If it does, your compiler is misconfigured or non-standard. Assigning a int* to a char* is not a valid form of assignment (see "simple assignment" 6.5.16.1). Neither is the opposite, char *p=a;.

Even if the code was rewritten as valid C, for example like this:

int i = *((int*)(p+1));

it would still be highly questionable code. First of all, if this results in a misaligned access, the code might invoke undefined behavior (6.3.2.3/7). Second, such code would violate strict pointer aliasing and invoke undefined behavior for that reason too (6.5/7).

And finally, given that p is a char*, the code printf("%d",*p); invokes undefined behavior because %d is not a valid conversion specifier for character pointers (7.21.6.1/9).

So there's no less than four possible cases of entirely different forms of undefined behavior in two rows of code... kind of impressive.


Now, if we assume that your particular system does not have any issues with misaligned access and that you have some non-standard compiler which doesn't follow the rules of pointer aliasing...

If so, on a 32 bit system, the array could get allocated in one of two possible ways:

02 00 00 00 03 00 00 00 04 00 00 00 // little endian
00 00 00 02 00 00 00 03 00 00 00 04 // big endian

In that case your first printf would print 2 or 0, depending on system, since it points at the very first byte, and you print the pointed-at contents of that byte.

If you then increment the char pointer by 1 and somehow manage to read the pointed-at contents as a 32 bit integer, you would get the data

00 00 00 03 // little endian
00 00 02 00 // big endian

Which equals the decimal values 50331648 (little) and 512 (big) respectively. Now what you wish to prove with that, or how the whole algorithm would be meaningful, I have no idea. There's not much to learn from this practice, apart from studying the many ways that will cause this code to fail.

Comments

0

This is a question about the width and endianness of ints and chars.

If we assume that you are on a machine with 32 bit little-endian ints and 8 bit chars, then it looks like this in memory:

a[0]      a[1]      a[2]
[2 0 0 0] [3 0 0 0] [4 0 0 0]

Where each printed character is 8 bits wide and each [ ] set is a 32 bit entry in a.

p, on the other hand, is a pointer to 8 bit chars. When p is set to point at a[0], it points to the first 8 bit entry in a, which is 2. The next 8 bit entry in a is the 0 just to the right of the 2.

If the machine you were working on had a different width or layout for ints, then the answer could be different.


Update:

Here is a in a 16bit little-endian int environment

a[0]  a[1]  a[2]
[2 0] [3 0] [4 0]

And in a 32bit big-endian int environment

a[0]      a[1]      a[2]
[0 0 0 2] [0 0 0 3] [0 0 0 4]

4 Comments

I'm running it on 16 bit compiler.
Won't the last printf extract 2 byte from the location it is pointing to ? I'm little bit confused due to this line p=(int *)(p+1);
So, that line is a bit tricky. If it wasn't for the (int *) cast it would be obvious that it is just incrementing p to point to the next char. However, it looks like it might be doing something else due to the cast. Don't be fooled! Due to C's order of operations, the increment happens before the cast, which is then re-cast back to a char*. So, the cast in that line isn't doing anything.
Downvoted, because this answer doesn't tell that p=(int *)(p+1); is undefined behaviour.
0

Judging by the use of the explicit cast (int*), your expectation of what happens in the line

p=(int *)(p+1);//What does this statement do ?

is misguided. That cast does not do anything useful. It is as good as:

p = p+1;

If you want p to point to the next number in a, you will need to use:

p = (int*)p+1;

or

p = a+1;

In a comment, you asked:

Will the last printf extract 2 bytes from the location it is pointing to or 1 byte ? I'm on 16 bit compiler ?

Neither of the printf statements will extract 2 bytes.

The printf statement

printf("%d ",*p);

is equivalent to:

char c = *p;        // Extract the char from p
int i = c;          // Cast the char to an int
printf("%d", i);    // Print the int

The output of the first printf call is 2 by coincidence -- a side effect of your platform being a little endian system. Had your platform been a big endian system, the output would have been 0.

10 Comments

How p=(int )(p+1); p = (int)p+1; these two are different ?
@gk123, No. But (int*)(p+1) is different from (int*)p+1.
A "cast" is implicitly "explicit". So yours is "explicit"ly explicit?;-) Still 1+, also for avoiding the so beloved phrase "integer promotion".
@alk, char* p = a; is also a cast but it is implicit.
@alk, you're right. A language lawyer I am not :) :)
|

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.