#include<stdio.h>
int main()
{
struct node
{
int a, b, c;
};
struct node num = {3, 5, 6};
struct node *ptr = & num;
printf("%d\n", *((int*)ptr + 1 + (3-2)));
return 0;
}

- 104,019
- 25
- 176
- 264

- 29
- 1
- 5
-
What is your question? – haccks Sep 21 '18 at 16:36
-
4The behaviour is *undefined*. It violates the [strict aliasing rule](https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule). – Weather Vane Sep 21 '18 at 16:41
-
@WeatherVane incorrect, there is no strict aliasing violation! This has been allowed ever since C89. It is accessing array (of 1) out of bounds why it is undefined. – Antti Haapala -- Слава Україні Sep 21 '18 at 16:54
-
@AnttiHaapala and your answer is incorrect too. The expression is accessing the 3rd element of a supposed array. It would have been less of a crime with `struct node { int a[3]; };` – Weather Vane Sep 21 '18 at 16:59
-
@AnttiHaapala: It does; there is no array and no guaranteed the members will use no padding like in an array. It's obfuscated bad code which pays the price. Such code should be deleted and burried. Dracula code: it always comes back. – too honest for this site Sep 21 '18 at 16:59
-
@WeatherVane strict aliasing says that totally unrelated pointer types cannot be used to modify / access objects. There is no padding at the beginning so the cast to `(int *)` is fine, there would be no undefined behaviour since it is the `int` object that is being accessed as an `int`. But the member `a` is *as if it were an array of 1* when it comes to pointer arithmetic. – Antti Haapala -- Слава Україні Sep 21 '18 at 17:09
-
@AnttiHaapala OP's code is `*( (int*)ptr + 2 );` which makes the assumption that there is no padding. – Weather Vane Sep 21 '18 at 17:11
-
And it would be still wrong even if there were no padding. – Antti Haapala -- Слава Україні Sep 21 '18 at 17:12
-
So it *is* wrong now? I did not condone it. – Weather Vane Sep 21 '18 at 17:12
2 Answers
lets simplify
printf("%d\n", *((int*)ptr + 1 + (3-2)));
to
int *ip = (int*)ptr;
int *ip2 = ip + 2;
int v = *ip2;
printf("%d\n", v);
ie.
'treating ptr as a pointer to a list of ints, display the value of the third one'.
The first step , treating a pointer to that struct as a pointer to an array of ints is taking advantage (misusing?) the fact that the first 3 fields are almost certainly going to be stored as 3 consecutive integers . Its a bit dodgy and I would hesitate to do it. I leave it to others to indicate whether or not its correct, in a strictly standard conforming way. I doubt it since we might have padding issues on some platforms

- 48,078
- 23
- 82
- 145
num
is a structure that is initialized to a=3
, b=5
and c=6
.
ptr
is a pointer that points to the structure. Everything is fine until the printf
line.
The construct
*((int*)ptr + 1 + (3-2)))
first casts ptr
that points into a pointer to int
:
(int*)ptr
The pointer points to the member a
and is well-defined.
Now 1 is added to this pointer:
(int*)ptr + 1
The pointer points to just past the member a
in the struct. Everything is well-defined unless this pointer is dereferenced. Finally 3 - 2
i.e. 1
is once more added to the resulting pointer.
(int*)ptr + 1
Behaviour is now undefined.
(int*)ptr + 1 + (3 - 2)
Then this invalid pointer is dereferenced causing undefined behaviour once more.
*((int*)ptr + 1 + (3 - 2))
The reason that the number 6 was printed and that seems like it is the 3rd member of the struct was just a fluke ;)

- 129,958
- 22
- 279
- 321
-
Really? An answer? There is not even a **specific** question. – too honest for this site Sep 21 '18 at 16:52
-
@toohonestforthissite ah I thought the question was "what does this code do", but it was "can someone explain the execution of the code?" for which the answer is "yes, someone can". – Antti Haapala -- Слава Україні Sep 21 '18 at 16:54
-
Point is, "explain this code" questions without a specific problem are way OT. Such questions are often given as homework to make the students learn reading code and have an example how to do things. But even if not, they are too broad and should be closed. (and that one can be understood with basic C knowledge taught by every C book. (said that: it invokes UB. – too honest for this site Sep 21 '18 at 16:56
-
so the correct answer to question is "yes". But thats too short for SO, and not what the questioner probably wants – pm100 Sep 21 '18 at 16:57
-
@pm100: Yes. Unfortunately you drew the wrong conclusion. – too honest for this site Sep 21 '18 at 17:03
-
thanks,can you also tell me how this is executed then,I think these 2 questions contradict each other char *arr[] = { "ant", "bat", "cat", "dog", "egg", "fly" }; function(arr); void function(char **ptr) { char *ptr1; ptr1 = (ptr += sizeof(int))[-2]; printf("%s\n", ptr1); } – Ayushya Rao Sep 21 '18 at 20:40
-
@AyushyaRao that depends on the size of `int`; on most generic computing platforms it is either 2 or 4 - then it is just equivalent to `char *ptr1 = ptr[4 - 2]` or `char *ptr = arr[2 - 2]`. – Antti Haapala -- Слава Україні Sep 22 '18 at 15:04
-