struct s{
int a;
char c;
};
int main()
{
struct s b = {5,'a'};
char *p =(char *)&b;
*p = 45;
printf("%d " , b.a);
return 0;
}
If *p
is changes to any character
than it prints ASCII
value of character , if *p
changed to any string ("xyz")
than it prints 36
. Why it's happening ?
Can you give memory map of structure s and *p ?
According to me mamory of struct
s as z-> (****)(*) assuming 4 byte for int .
and when s initialize than it would have become (0000000 00000000 00000000 00000101)(ASCII OF char a)
and *p points to starting address of z . and *p is a character pointer so it will be store ASCII value at each BYTE location ie at each * will be occupied by ASCII of char . But now we make it to 45 so z would have become (45 0 0 5 )(ASCII of char a)
. But it's not true why ?
your struct looks in little endian like:
00000101 00000000 00000000 00000000 01100001
so p
points to the 5
and overwrite it. at the printf the 4 little endian bytes print the 45
.
if you would try it on big endian 754974725
would be the result, because p
points to the MSB side of the int.
a simple test program to find out if you are on little or big endian:
int main()
{
int a = 0x12345678;
unsigned char *c = (unsigned char*)(&a);
if (*c == 0x78)
printf("little-endian\n");
else
printf("big-endian\n");
return 0;
}
When you write to the struct through a char *
pointer, you store 45
in the first byte of the struct. If you are on a Little-Endian implementation, you will write to the low end of ba
. If you are on a Big-Endian implementation, you will write to the high end of ba
.
Here is a visualization of what typically happens to the structure on an implementation with 16-bit ints, before and after the assignment *p=45
. Note that the struct is padded to a multiple of sizeof(int)
.
Before: a [05][00] (int)5 c [61] [ ] After: a [2d][00] (int)45 c [61] [ ]
Before: a [00][05] (int)5 c [61] [ ] After: a [2d][05] (int)11525 c [61] [ ]
With larger ints, there are more ways to order the bytes, but you are exceedingly unlikely to encounter any other that the two above in real life.
However , The next line invokes undefined behaviour for two reasons:
printf("%d " , b.a);
ba
through a pointer of a different type. This may give ba
a "trap representation", and reading a value containing a trap representation causes undefined behaviour. (And no, you are not likely to ever encounter a trap representation (in an integer type) in real life.) #include <stdio.h>
. Undefined behaviour means that anything could happen, such as printing the wrong value, crashing your program or (the worst of them all) doing exactly what you expect.
The C standard guarantees that the address of the first member of a structure is the address of the structure. That is, in your case,
int* p =(int*)&b;
is a safe cast. But there is no standard way of accessing the char
member from the address of the structure. This is because the standard does not say anything about the contiguity of successive members in memory: in fact the compiler may or may not insert gaps (called structure packing) between members to suit the chipset.
So what you're doing is essentially undefined.
Because, this
*p = 45;
Changes the value of what p points to to 45. And you made p point to b.
try this Pointers to structure.
#include<stdio.h>
struct s{
int a;
char c[1];
};
int main()
{
struct s *p;
struct s b = {5, 'a'};
p = &b;
printf("%d %s", p->a, p->c);
return 0;
}
if you want Pointers as structure member instead of an array of char. try this..
#include<stdio.h>
struct s{
int a;
char *c;
};
int main()
{
struct s b = {5, "a"};
printf("%d %s", b.a, b.c);
return 0;
}
char *p = (char*) &b;
- in this line, p
points to the beginning of b
struct as a char pointer.
*p = 45;
writes 45 to the memory space of b
which is can be accessed by ba
as well.
when you print printf("%d ", ba);
you'll print the 45 stored in the stack memory assigned as a
member of struct b
you'll get 45.
try debugging it yourself and you'll see it in the watch window
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.