Сравнение битового поля с целым числом (отрицательное), undefined или ошибками компилятора?
Вот небольшая программа. Должно ли это печатать 0 или 1 или имеет поведение undefined?
#include <stdio.h>
struct S0 {
unsigned f1 : 1;
};
struct S0 s;
int main (void) {
int x = -3;
int y = x >= (0, s.f1);
printf ("%d\n", y);
return 0;
}
Это взято из теста resent CSmith, и этот случай обсуждается более здесь.
В частности, GCC, KCC и CompCert выдает 0, а MSVC 2010, ICC 12.0.2 и последние результаты Clang 1.
Ответы
Ответ 1
Интересный вопрос.
В соответствии с проектом стандарта C99 6.5.17.1 тип (0, s.f1)
совпадает с типом s.f1
, который (на 6.7.2.1.9) является "целым числом без знака, состоящим из 1 бит". Это арифметический тип из-за того, что он является целым типом, его точность равна 1 (в соответствии с 6.2.6.2.6 и 6.2.6.1.3 не содержит битов заполнения), поэтому его ранг меньше, чем у int
( по второму элементу под 6.3.1.1.1, int имеет точность не менее 15, так как он должен иметь возможность представлять значения в диапазоне от -32767 до 32767 (см. 5.2.4.2.1)).
Поскольку как x
, так и выражение (0, s.f1)
имеют арифметический тип, выполняются обычные арифметические преобразования (в соответствии с 6.5.8.3). Так как int может представлять весь диапазон значений s.f1
, ему присваивается (подписанный) int (согласно 6.3.1.1.2). Тогда, поскольку оба операнда являются (подписанными) ints, общий реальный тип подписан int (согласно 6.3.1.8), и поэтому результат сравнения должен быть 0.
Ответ 2
AFAIK, тип s.f1
равен unsigned int
. Я считаю, что оператор запятой - красная сельдь; это сравнение эквивалентно int y = x >= s.f1;
. Применяя "обычные арифметические преобразования" (C99 6.3.1.8), при выполнении сравнения x
преобразуется в unsigned int
; это преобразование хорошо определено (это приведет к UINT_MAX-2
, поэтому оно будет больше. Таким образом, ответ должен быть 1
.
Ответ 3
Я добавлю это здесь, комментарий № 39 от Rajan Bhakta, здесь,
Это двусмысленность в стандарте, который был очищен в Предстоящая последняя редакция стандарта ISO C (обычно известная как C1X пока он не будет ратифицирован) в пункте 6.3.1.1 параграфа 2. В сущности, тип битового поля (из результата выражения запятой) преобразуется к int, и, следовательно, сравнение представляет собой подписанное сравнение int. В сущность, стандарт C1X говорит, что значение y равно 0.
Буду признателен, если кто-нибудь сможет подтвердить это.