#include<stdio.h>
#include<stdlib.h>
struct test{
char b;
开发者_如何学编程 int a;
int c ;
};
int main()
{
struct test inst;
struct test *ptr_test = &inst;
char * ptr_ch;
int* ptr_i;
/*ptr_ch = (char *) ptr_test;*/
ptr_ch = (char*)ptr_test;
ptr_i = (int *) ptr_test;
*ptr_ch = 'b';
*ptr_i = 13;
printf("char b = %c, int a = %d int c = %d", inst.b, inst.a, inst.c);
return 0;
}
I expected the output to give the appropriate values of a,b and garbage value of c. But on the terminal, if I do ./a.out the output is:
, int a = 134513785 int c = 13173540
When I do $./a.out > tmp; vim tmp, the output is:
char b = ^M, int a = 134513785 int c = 12714788
What is the problem?
I wanted to access individual fields of the struct using typecasting.
for instance, I wanted to know another way to return the value of &(inst.a).
Your pointers
ptr_ch = (char*)ptr_test;
ptr_i = (int *) ptr_test;
do not automatically refer to the first apropriate member variable (in your case b and a). Rather they just reinterpret the pointer to the structure as pointer to char
or int
, so they point to the same location, the address of your structure. With the char
you might be lucky that it's the first member and you are really pointing to the char
, but your int
pointer points to the same address and therefore overwrites it with platform- and compiler-dependent garbage.
So don't do those kinds of things (or do them when you really know what you are doing and, more important, where (on what platform and with what compiler) you are doing it).
ptr_ch and ptr_i point to the same memory location:
ptr_ch = (char*)ptr_test;
ptr_i = (int *) ptr_test;
when you do the following you are reading from the same memory address:
*ptr_ch = 'b'; //write the first sizeof(char) byte of the structure ptr_test
*ptr_i = 13; //write the first sizeof(int) bytes of the structure ptr_test overwriting some bytes wrote before
You should eventually do something like:
ptr_ch = &(ptr_test->b);
*ptr_ch = 'b';
ptr_i = &(ptr_test->a);
*ptr_i = 13;
Why would you use the typecasting? Why not do the following:
ptr_ch = &(ptr_test->b);
ptr_i = &(ptr_test->a);
13
is decimal for an ASCII carriage return - when you do *ptr_i = 13;
, you're setting b
to that 13. If you change your print out to look like:
printf("char b = %c (%d), int a = %d int c = %d", inst.b, inst.b, inst.a, inst.c);
You'll see that you get:
(13), int a = 1 int c = 1606416024
as output instead. The carriage return character is causing your char b
output to get overwritten by the output following the carriage return character. It might be more obvious if you used a different number than 13. For example, using 86, you'll get:
char b = V, int a = 1 int c = 1606416024
as the output. The reason a
and c
don't make sense is because they're uninitialized.
You can't just typecast a structure pointer to a pointer of another type and expect the compiler to extract a pointer to a field inside that structure for you - that's not how it works. I think you might have been trying to do this:
ptr_ch = &ptr_test->b;
ptr_i = &ptr_test->a;
Here's a complete example program that does what I think you're trying for:
#include<stdio.h>
struct test {
char b;
int a;
int c;
};
int main(void)
{
struct test inst = {0, 0, 0};
struct test *ptr_test = &inst;
char *ptr_ch;
int *ptr_i;
ptr_ch = &ptr_test->b;
ptr_i = &ptr_test->a;
*ptr_ch = 'b';
*ptr_i = 86;
printf("char b = %c, int a = %d int c = %d\n", inst.b, inst.a, inst.c);
return 0;
}
And its output:
char b = b, int a = 86 int c = 0
You should use the strict conforming offsetof macro, which calculates the offset of any struct element from struct begin:
ptr_ch = (char*)ptr_test;
*ptr_ch = 'b';
ptr_i = ptr_ch + offsetof(struct test,a);
*ptr_i = 13;
ptr_i = ptr_ch + offsetof(struct test,c);
*ptr_i = 14;
精彩评论