2009-11-15 2 views
15

Почему выражение, указанное внутри оператора запятой (например, пример ниже), не считается постоянным выражением?Оператор запятой C

Например,

int a = (10,20) ; 

, когда в глобальном масштабе дает ошибку «инициализатор не является постоянной», хотя оба выражения, разделенные оператором запятой константы (постоянные выражения). Почему все выражение не рассматривается как постоянное выражение? Для уточнения я прочитал What does the ‘,’ operator do in C? и Uses of C comma operator. Они не рассматривали этот аспект оператора запятой.

+0

Спасибо Rossel. Теперь текст имеет большую читаемость. –

+0

Возможный дубликат [Что делает оператор запятой \ ', \' do in C?] (Http://stackoverflow.com/questions/52550/what-does-the-comma-operator-do-in-c) –

ответ

33

Раздел 6.6/3, «Константные выражения», стандарта ISO C99 - это раздел, который вам нужен. В нем говорится:

Постоянных выражения не должны содержать назначение, увеличение, уменьшение, вызов функции, или запятую операторы, кроме случаев, когда они содержатся в подвыражения, который не оценки.

В обосновании документа C99 от ISO, есть этот маленький фрагмент кода:

Целочисленные константное выражение должно включать только числа познаваемых во время трансляции, а операторы без побочных эффектов.

И, так как нет смысла использовать оператор запятой на всех если вы не полагаться на побочные эффекты, это бесполезно в постоянном выражении.

Под этим я имею в виду, что нет абсолютно никакой разницы между двумя сегментами кода:

while (10, 1) { ... } 
while  (1) { ... } 

с 10 фактически не делать ничего. На самом деле,

10; 

это вполне допустимо, хотя и не очень полезно, заявление C, то большинство людей не понимают, пока они не получат, чтобы лучше знать язык.

Однако есть есть разница между этими двумя утверждениями:

while ( 10, 1) { ... } 
while (x=10, 1) { ... } 

Там побочный эффект в последнем использовании оператора запятая, который должен установить переменную x в 10.

Относительно того, почему они не любят побочные эффекты в постоянных выражениях, вся точка постоянных выражений заключается в том, что их можно оценивать во время компиляции, не требуя среды выполнения. - ISO делает различие между трансляцией (время компиляции) и среды исполнения (времени выполнения).

Разгадка, почему ISO передумала требует составителей для предоставления информации среды исполнения (кроме материала, содержащегося в заголовочных файлах, таких как limits.h) можно найти чуть позже в обоснование документа:

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

Иными словами, ИСО не хотел, чтобы производители кросс-компиляторов были обременены переносом среды выполнения для всех возможных целей.

+5

+1: Я просто искал это. Я считаю, что более глубокая причина заключается в том, что оператор запятой вводит точку последовательности. –

+0

Спасибо paxdiablo. Обращение к обоснованному документу - это то, что я должен был очистить от своих сомнений. –

-2

gcс принимает это:

int a = (10,20) ; 

int main() { 
    printf("%d\n",a); 
} 

и печатает 20. Наверное, это проблема вашего компилятора?

+0

Мой gcc (4.3.3), без флагов, не принимает его. –

+0

Какая версия GCC, на какой платформе с помощью каких флагов? Я попытался с GCC 4.0.1 на MacOS X 10.5.8 без флагов и получить ошибку. –

+0

gcc версия 3.4.4 (cygming special, gdc 0.12, используя dmd 0.125) Cygwin, без флагов. –

6

ISO/IEC 9899: 1999 6.6/3 (константные выражения) указывает, что выражения contant не должны содержать запятые (если часть не выраженного сублиценмента не определена), поэтому (10,20) не является константным выражением по определению ,

Обоснование должно состоять в том, что, поскольку значение первой части выражения для запятой не используется, оно существует только для его побочных эффектов, и для постоянных выражений не имеет смысла иметь побочные эффекты.

0

Компилятор не считает это постоянным выражением, так как переменная является автоматической. Он может быть оценен во время выполнения и получить значение. Попробуйте сделать переменную static, и вы увидите то же сообщение об ошибке, что и для компилятора, для которого требуется постоянное выражение.