我正在玩结构并尝试使用偏移来获取它们的值,这是我的代码
#include <stdio.h>
#include <stddef.h>
typedef struct abcd{
int a,b;
double c,d;
}abcd;
int main()
{
abcd teste = {.a = 3, .b = 5, .c = 7, .d = 9};
printf("value of a: %d //value of b: %d\n",*( (char*) &teste), *((char*) &teste + offsetof(abcd, b)) );
return 0;
}
输出:value of a: 3 //value of b: 5
一切正常,但是当我将printf更改为
时printf("value of a: %d value of b: %d\n", *( &teste), *((char*) &teste + offsetof(abcd, b)) );
//No casting to (char*) in value of a
我得到了输出:value of a: 5 value of b: 1360854088
为什么会这样?
答案 0 :(得分:2)
printf("value of a: %d value of b: %d\n", *( &teste), *((char*) &teste + offsetof(abcd, b)) );
这会通过值传递teste
,这比单个int占用更多空间。第二个%d
可能会从第一个arg的某些字节获得输入。编译器警告清楚地说明了这一点:
$ clang-3.5 -Wall bad-printf.c -O3
bad-printf.c:12:48: warning: format specifies type 'int' but the argument has type 'abcd' (aka 'struct abcd') [-Wformat]
printf("value of a: %d value of b: %d\n", *( &teste), *((char*) &teste + offsetof(abcd, b)) );
~~ ^~~~~~~~~~
$ gcc -Wall bad-printf.c -O3
bad-printf.c: In function ‘main’:
bad-printf.c:12:5: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘abcd’ [-Wformat=]
printf("value of a: %d value of b: %d\n", *( &teste), *((char*) &teste + offsetof(abcd, b)) );
^
$ ./a.out
value of a: 5 value of b: 0
$ uname -a
Linux tesla 3.19.0-22-generic #22-Ubuntu SMP Tue Jun 16 17:15:15 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
它还将一个单字节字符传递给printf
,作为第三个arg(格式字符串后面的第二个arg)。寄存器中的其他字节(或堆栈中的其他字节,如果您为过时的32位x86编译)可能是剩下的其他字节。
检查装配输出。您可能会发现来自&abcd.b
的单字节负载,其他字节保持不变。
你告诉printf(使用%d
)你传递了一个完整的int
。如果您只想打印8位整数(因此它不会将填充视为数据),则需要格式说明符的大小前缀。
答案 1 :(得分:0)
printf%d但是你传递了sturct adcd,这是一个未定义的动作,结果是未定义的,它应该考虑printf.c的实现。
我的代码:
typedef struct abcd{
int a,b;
double c,d;
}abcd;
int main()
{
abcd teste = {.a = 3, .b = 5, .c = 7, .d = 9};
printf("value of a: %d //value of b: %d\n",*( (char*) &teste), *((char*) &teste + offsetof(abcd, b)) );
printf("%d\n", offsetof(abcd, b));
printf("value of a: %p value of b: %p\n", ( &teste), ((char*) &teste + offsetof(abcd, b)) );
printf("value of a: %d value of b: %d\n", teste, *((char*) &teste));
printf("value of a: %p value of b: %p\n", &teste, ((char*) &teste));
printf("value of a: %d value of b: %d\n", teste, *((char*) &teste));
//No casting to (char*) in value of a
return 0;
}
result:
value of a: 3 //value of b: 5
4
value of a: 0x7fff86f203b0 value of b: 0x7fff86f203b4
value of a: 3 value of b: -2114388464
value of a: 0x7fff86f203b0 value of b: 0x7fff86f203b0
value of a: 3 value of b: -2114388464
未定义的过程导致未知结果