Reputation: 21
#include<stdio.h>
struct test{
int a;
int b;
}m;
int main()
{
m.a=5;m.b=7;
struct test *p;
p = &m;
printf("p[0] = %d\n",*(p+0));
printf("p[1] = %d\n",*(p+1));
return 0;
}
I get the following Ouput:
p[0] = 5 p[1] = 0
Can someone please explain this behavior? Is there a way to print all struct members using index?
Sorry about the typo.
(Updated)
As I could print 1st element using index 0 , though the type of pointer is of "struct test type" and 1st member is an integer , I could get the correct value. Hence, the question triggered about the cause of this behavior. And if all the members can be accessed using the index just like the 1st member was accessed.
Upvotes: 1
Views: 3161
Reputation: 4043
First, you have a typo in your code.
Please correct it from p = &a;
to p = &m;
, so that the error complained by the compiler shall be removed.
Second, I guess you expect the output to be p[0] = 5 and p[1] = 7. To achieve that, modify your code from
printf("p[0] = %d\n",*(p+0));
printf("p[1] = %d\n",*(p+1));
to
printf("p[0] = %d\n",p->a);
printf("p[1] = %d\n",p->b);
can work.
Upvotes: 1
Reputation: 134286
In your code,
printf("p[0] = %d\n",*(p+0));
printf("p[0] = %d\n",*(p+1));
invokes undefined behavior as
%d
format specifier.*(p+1)
So, the output cannot be explained or justified in any way.
Now, that said, let's analyze the code a bit.
First of all,
p = &a;
is wrong, as there is no variable called a
. There is a member variable a
for the structure variable m
, which can be accessed as m.a
. So, you can somehow write
p = (struct test*) &m.a;
Now, using the address of the first element of the structure as the structure address is valid as there is no padding at the beginning of the structure. But that does not mean, you can apply pointer arithmetic directly on the structure pointer p
and get each member variable, mainly because
p
is of type struct test
(Though you can get around by casting) Upvotes: 3
Reputation: 10430
I compiled your code with gcc and i got.
In function ‘main’:
error: ‘a’ undeclared (first use in this function)
p = &a;
^
note: each undeclared identifier is reported only once for each function it appears in
warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘struct test’ [-Wformat=]
printf("p[0] = %d\n",*(p+0));
^
warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘struct test’ [-Wformat=]
printf("p[0] = %d\n",*(p+1));
Assuming you meant p=&m
, here is my explanation
printf("p[0] = %d\n",*(p+0));
printf("p[0] = %d\n",*(p+1));
First analyse whether deferring pointer like you did in printf function is correct or not.
The *(p+0)
will give you the access to the struct test variabe m
. As, you have assigned the address of a variable of type struct test
to the pointer p
, deferring pointer *p
or *(p+0)
will give you the access to the variable m
. But the address assigned to the pointer is of a single variable not of the array of type struct test
, deferring (p+1)
will give you UNDEFINED BEHAVIOR. For example, *(p+1)
would have worked if (not in printf statement
)
struct test m[20];
struct test *p;
(*(p+0)).a=2;
(*(p+1)).a=5;
Is there a way to print all struct members using index?
You can. But there is no overloading of operators in c. So, you can achieve this by -
printf("a=%d, b=%d", p->a, p->b);
If pointer p
points to array of type struct test
, then you can use index in printf as
printf("a=%d, b=%d of %dth element", p[i].a, p[i].b, i);
My suggestion for your future code experimentation will be first analyse warning and error given by your code. The warnings can help to rectify most of the bugs in your code. I always compile my c/c++ code with gcc/g++ compiler and use flags like -Wall, -Wshadow, -Wextra. You can google a warning if you don't understand it.
Upvotes: 2
Reputation: 505
You are assigning the address of a
to p
directly. a
is a member of m
and so cannot be accessed directly. And as of your code, you should use an integer pointer for your arithmetic.
you need to modify a part of your code
struct test *p;
p = &a;
to
int *p;
p = &m.a;
now the code should work as you desire.
Upvotes: 0
Reputation: 133879
Get a proper compiler. Compiled with default settings on GCC 5, the compilation spits out:
foo.c: In function ‘main’:
foo.c:12:10: error: ‘a’ undeclared (first use in this function)
p = &a;
^
foo.c:12:10: note: each undeclared identifier is reported only once for each function it appears in
foo.c:13:12: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘struct test’ [-Wformat=]
printf("p[0] = %d\n",*(p+0));
^
foo.c:14:12: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘struct test’ [-Wformat=]
printf("p[0] = %d\n",*(p+1));
^
Perhaps you meant p = &m;
.
After that your code invokes undefined behaviour. %d
expects that the corresponding argument be an int, yet you provide a struct test
. Furthermore on the latter print, the pointer is pointing to uninitialized memory after the m
, and garbage is printed. Even the fact that you had 5
printed in the first case cannot be relied on. The C standard does not explain that why or why not this happens, the C standard says "at this time it is ok for the compiler to generate code that prints 42342, crash the program, or do whatever else, and it is fine by this standar d."
In C compilers the warnings usually mean "standard violations" in which case undefined behaviour is probable. A newcomer to C programming language should always consider all compiler warnings especially with default settings as being fatal errors.
Upvotes: 1