Чем объясняется вывод этого кода на C? - PullRequest
0 голосов
/ 30 января 2011
#include <stdio.h>

struct abc{
  int a;
  int b;
} xyz;

int main()
{
  xyz.a = 10;
  xyz.b = 20;
  printf("%d %d", xyz, xyz.a);
}

Вывод вышеуказанной программы равен 10 20.

Если я добавлю еще один оператор printf как

printf("%d %d %d", xyz, xyz.a, xyz.b);

, то получится 10 20 10.

Чем это объясняется?

Ответы [ 2 ]

15 голосов
/ 30 января 2011

Это потому, что вызов printf помещает всю структуру xyz в стек, и эта структура (в данном случае) состоит из двух целых чисел.xyz.a в этом случае игнорируется, поскольку он находится за пределами области стека, о которой заботится printf.

Хотя поведение не определено (a) , так что может произойти что угодноСлучай можно объяснить, потому что оператор printf("%d %d",xyz,xyz.a);, вероятно, помещает xyz и xyz.a в стек что-то вроде:

xyz.a | 10 |    |
xyz   | 20 |    | Stack grows downward.
      | 10 |    V

и самого кода printf, потому что ему присвоено два %d s, напечатает 10 внизу и 20. Иными словами, это несоответствие между строкой формата и параметрами.

Когда вы добавляете еще один %d, он печатает то, что считаеттретий аргумент (но на самом деле второй), верхние 10 в приведенной выше диаграмме.

Я должен отметить, что полагаться на такое поведение не очень хорошая идея.Это может измениться, когда вы переключаете компиляторы, версии компилятора или, возможно, даже в нечетные дни: -)

Хорошие компиляторы, такие как gcc, на самом деле заглядывают в аргументы printf, чтобы уловить это как потенциалошибка:

pax$ cat qq.c
#include<stdio.h>
struct abc { int a; int b; } xyz;
int main (void) {
    xyz.a=10;
    xyz.b=20;
    printf("%d %d",xyz,xyz.a);
    return 0;
}

pax$ gcc -Wall -o qq qq.c
qq.c: In function 'main':
qq.c:6: warning: format '%d' expects type 'int',
        but argument 2 has type 'struct abc'
qq.c:6: warning: format '%d' expects type 'int',
        but argument 2 has type 'struct abc'

(a) Начиная с c99, раздел 7.19.6.1/9: Если какой-либо аргумент не является правильным типом для соответствующей спецификации преобразования, поведениене определено.

2 голосов
/ 30 января 2011

Вы вызвали неопределенное поведение ; любой результат разрешен.

7.19.6.1 Функция fprintf
...
9 Если спецификация преобразования недопустима, поведение не определено. 248) Если какой-либо аргумент неправильный тип для соответствующей спецификации преобразования, поведение не определено.

Акцент мой. xyz имеет тип struct abc, но printf ожидает, что аргумент будет иметь тип int.

ответ paxdiablo - достойное посмертное объяснение того, как такой результат может произойти, но это применимо только к вашим конкретным обстоятельствам. Измените что-нибудь в отношении кода, среды перевода или среды выполнения, и результат, вероятно, будет другим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...