Почему результаты этих двух выражений различаются?

Я разрабатывал ответ на другой вопрос и наткнулся на кирпичную стену, объясняющую результат, вычисленный GCC для определенного выражения. (Мой ответ был связан с функциями inline; изначально код состоял из двух исходных файлов и заголовка. Я объединил их в один исходный файл, не используя inline.)

Код

//static inline int somename(int x, int y) { return x + y + 1; }
static int somename(int x, int y) { return x + y + 1; }
extern int nothername(int x, int y);

#include <stdio.h>

int main(void)
{
    printf("somename(1,2)   = %d\n", somename(1, 2));
    printf("nothername(2,1) = %d\n", nothername(2, 1));
    return 0;
}

int nothername(int x, int y)
{
    printf("x = %d, y = %d, somename(x, y) = %d, cn = %d\n",
           x, y, somename(x, y),  ((y != 0) ? x / y : x));
    int z1 = somename(x, y) +  (y != 0) ? x / y : x;
    int z2 = somename(x, y) + ((y != 0) ? x / y : x);
    printf("z1 = %d, z2 = %d\n", z1, z2);
    return somename(x, y) + (y != 0) ? x / y : x;
}

Ожидаемый результат

somename(1,2)   = 4
x = 2, y = 1, somename(x, y) = 4, cn = 2
z1 = 6, z2 = 6
nothername(2,1) = 6

Фактический результат

somename(1,2)   = 4
x = 2, y = 1, somename(x, y) = 4, cn = 2
z1 = 2, z2 = 6
nothername(2,1) = 2

Вопрос:

  • Почему z1 не 6?

Окружающая среда

Это работает на MacOS X 10.6.7. Я использовал GCC 4.2.1, предоставленный Apple как часть XCode 3; Я использовал GCC 4.6.0, который я скомпилировал. Первоначальные эксперименты были связаны с inline функциями в C++; эквивалентный код с использованием cout и т. д. дает те же результаты вычислений. Я проверил, что somename(2, 1) и somename(1, 2) дают 4.


gcc c
person Jonathan Leffler    schedule 17.04.2011    source источник


Ответы (1)


Приоритет ?: очень низкий, поэтому

int z1 = somename(x, y) + (y != 0) ? x / y : x;

интерпретируется как

int z1 = (somename(x, y) + (y != 0)) ? (x / y) : (x);

что (4 + 1) ? (2 / 1) : 2, что 2.

Это также объясняет, почему добавление круглых скобок при вычислении z2 устранило проблему.

person dfan    schedule 17.04.2011
comment
О, черт! Конечно... Я знал, что это должен быть глупый ментальный блок с моей стороны. (Беда была в том, что это был ментальный блок с моей стороны!) Спасибо. - person Jonathan Leffler; 17.04.2011