Вопрос

В C.1.3 IS C ++ (2003 г. Он также присутствует в IS C ++ 11) стандарт указывает на разницу между ISO C и C ++;а именно для

родовое слово

sizeof(0, arr) возвращает код сгенерированного кода на C, но сгенерирует код кода на С ++.

Я не могу найти документации для кода sizeof(char*) с двумя аргументами.Очевидной альтернативой является оператор запятой, но я так не думаю: 100 в C - это sizeof;sizeof(arr) - это 100sizeof(0, arr), и sizeof(char*) являются генерирующим кодом кода в C ++.

Возможно, я упускаю из виду весь смысл ИБ в этом контексте.Кто-нибудь может помочь?Это похоже на вопрос, который обсуждался еще в 2009 году, но никто не упомянул ИГ, и я не думаю, что был дан правильный ответ.


Изменить : на самом деле IS говорит об операторе запятой.Итак, по какой-то причине sizeof(0, arr) возвращает код sizeof(arr) на C, но код 100 на C ++.Почему?

Это было полезно?

Решение

В C тогда массив распадается на указатель из-за различной спецификации оператора запятой по отношению к rvalue и lvalues (не единственное место, где можно найти такую разницу).В C ++ массив остается массивом, что дает правильный результат.

Другие советы

В C оператор запятой не создает lvalue, следовательно, массив arr, который является lvalue, распадается на тип указателя, который является rvalue (в данном случае). Таким образом, sizeof(0,arr) становится эквивалентным sizeof(char*) из-за преобразования lvalue-to-rvalue .

Но в C ++ оператор запятой дает lvalue. Преобразование lvalue-to-rvalue отсутствует. Таким образом, sizeof(0,arr) остается прежним, что эквивалентно sizeof(char[100]).

Кстати, sizeof - это не функция, это оператор. Таким образом, следующий код является полностью допустимым для C ++ (и для C, если представить себе printf вместо cout):

родовое слово

Демо: http://www.ideone.com/CtEhn

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

4 операнда с 3 операторами-запятыми; как и в 1+2+3+4, здесь 3 оператора, 4 операнда.

Приведенное выше эквивалентно следующему (действительно в C ++ 0x):

родовое слово

Демоверсия: http://www.ideone.com/07VNf

Итак, оператор запятая заставляет вас почувствовать , что существует множество аргументов . Здесь запятая - это оператор, но при вызове функции запятая НЕ является оператором, а просто разделителем аргументов.

родовое слово

Таким образом, sizeof(a,b,c,d) работает с типом результата операторов , точно так же, как sizeof(1+2+3+4) работает с типом результата операторов +.

Также обратите внимание на то, что вы не можете написать код сгенерированного кода именно потому, что оператор запятая не может работать с типами . Он работает только с значением . Я думаю, что sizeof(int, char, short) - единственный оператор в C и C ++, который также может работать с типами . В C ++ есть еще один оператор, который может работать с типами . Его имя - sizeof.

Это оператор запятой. И разница, о которой вы говорите, не имеет абсолютно никакого отношения к сгенерированному кодовому методу. На самом деле разница заключается в lvalue-to-rvalue, array-to-pointer и аналогичном поведении распада между языками C и C ++.

Язык C в этом отношении довольно удобен для триггеров: массивы распадаются на указатели практически сразу (за исключением очень небольшого числа конкретных контекстов), поэтому результат выражения sizeof имеет тип 0, arr. Это эквивалентно char *.

В языке C ++ массивы гораздо дольше сохраняют свою «массивность». При использовании в контексте операторов 0, (char *) arr массивы операторов не распадаются на указатели (а lvalue не распадаются на rvalues), поэтому в C ++ тип выражения , по-прежнему является 0, arr.

Это то, что объясняет различие в поведении кода сгенерированного кода в этом примере. Оператор char[100] - еще один пример оператора, который демонстрирует аналогичное различие в поведении распада, то есть sizeof даст вам разные результаты в C и C ++. По сути, все это связано с тем, что операторы C обычно не сохраняют ценность своих операндов. Для демонстрации такого поведения можно использовать множество операторов.

Это не кодовый код, принимающий два аргумента.sizeof - это оператор, а не функция.

Учтите, что sizeof - это выражение с использованием оператора запятой, а все остальное становится на свои места.

sizeof не принимает два аргумента. Но это тоже не функция, поэтому код (...) не ограничивает аргументы функции, они просто необязательная часть синтаксиса и принудительная группировка. Когда ты пишешь sizeof(0, arr), аргумент sizeof - это одно выражение 0, arr. Одно выражение с оператором запятой, которое оценивает выражение слева от запятой, выдает его значение (но не его побочные эффекты), затем оценивает выражение справа от запятой, и использует его значение как значение полного выражения.

Я не уверен насчет C, но это может быть разница между langauges. В C ++ преобразование массива в указатель не происходит, если необходимо; в C, если я правильно помню, стандарт говорит, что это всегда имеет место, за исключением определенных контекстов. В том числе как оператор генерирования кодового кода. В этом случае, поскольку оператор запятой не имеют ограничения относительно типов его операндов, Преобразование массива в указатель не выполняется в C ++. В C оператор запятой не указан в исключениях, поэтому преобразование массива в указатель действительно происходит. (В этом случае массив является операндом оператора запятой, а не генерального кода кода.)

Лучший способ понять, что здесь может происходить, - это взглянуть на грамматику в стандарте. Если мы посмотрим на черновой вариант стандартного раздела C99 6.5.3 Унарные операторы параграф 1 , мы увидим, что грамматика для sizeof:

родовое слово

Итак, второй вариант неприменим, но как в этом случае применяется код генерирующего кода? Если мы посмотрим на раздел sizeof unary-expression Expressions из проекта стандарта и проработаем грамматику следующим образом:

родовое слово

мы получаем круглые скобки вокруг выражения , и теперь нам просто нужно взглянуть на грамматику для оператора запятой из раздела A.2.1 оператора запятой и мы видим:

родовое слово

Итак, у нас есть:

родовое слово

И выражение , и выражение-присваивания могут привести нас к первичному-выражению , имеющему следующую грамматику:

родовое слово

и 6.5.17 - это константа , а 0 - это идентификатор , поэтому мы имеем:

родовое слово

Итак, что здесь делает оператор запятой ? В разделе arr в абзаце 2 говорится:

<цитата>

Левый операнд оператора запятой оценивается как недействительное выражение; Существует точка последовательности после ее оценки. Затем оценивается правый операнд; результат имеет свой тип и значение. 97)

поскольку оператор запятой не является одним из исключений, когда массив не преобразуется в указатель, он дает указатель ( это описано в разделе 6.5.17 Lvalues, массивы и указатели функций ), что означает:

родовое слово

В C ++ грамматика очень похожа, поэтому мы заканчиваем в том же месте, но операторы запятой работают по-другому. В черновике стандартного раздела C ++ создается оператор запятой :

<цитата>

[...] Тип и значение результата - это тип и значение правого операнда; результат имеет ту же категорию значений, что и его правый операнд [...]

so и преобразование массива в указатель не требуется, поэтому мы получаем:

родовое слово

Как уже было сказано, и я хочу добавить только одну вещь, sizeof - это оператор, принимающий либо выражение, либо выражение приведения. По этой причине я взял за правило писать парантез до размера только , если это выражение приведения.

родовое слово

Напишу

родовое слово

но

родовое слово

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top