2015-07-26 1 views
1

я играл и структуры пытаюсь получить их значение с помощью смещения, это мой кодНе может понять, почему я получил эти результаты, используя структуру смещения в C

#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

Почему это происходит?

+3

Ваших второй 'printf' вы на самом деле даете полную структуру (' * (& TESTE) ') для'% формат d' спецификатора , Это приведет к смещению позиций стека последующих значений для последующих спецификаторов в строке формата. – lurker

+0

@GRC Можете ли вы рассказать об этом немного? Кастинг - очень полезная функция при правильном использовании. – tangrs

+0

'printf (" значение a:% d значение b:% d \ n ", * (int *) (& teste), * (int *) ((char *) & teste + offsetof (abcd, b))) ; ' – BLUEPIXY

ответ

2
printf("value of a: %d value of b: %d\n", *(&teste), *((char*) &teste + offsetof(abcd, b))); 

Это проходит teste по значению, которое занимает больше места, чем один Int. Второй %d, вероятно, будет получать входные данные из некоторых байтов первого аргумента. Компилятор предупреждения сделать это ясно:

$ 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, как 3-й арг (второй аргумент после строки формата). Остальные байты в регистре (или в стеке, если вы скомпилированы для устаревшего 32-битного x86), могут быть оставлены от чего-то другого.

Проверьте вывод сборки. Вероятно, вы найдете однобайтную нагрузку от &abcd.b, оставив остальные байты незатронутыми.

Вы сказали printf (используя %d), что вы передали ему полный текст int. Если вы хотите только напечатать 8-битное целое число (поэтому он не будет обрабатывать заполнение как данные), вам нужен префикс размера для вашего спецификатора формата.

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 

результат unkonwn undfined процесс причины