无法理解为什么我在C中使用struct offset获得这些结果

时间:2015-07-26 01:24:45

标签: c struct offset

我正在玩结构并尝试使用偏移来获取它们的值,这是我的代码

#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

为什么会这样?

2 个答案:

答案 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

未定义的过程导致未知结果