размер принятия двух аргументов
-
27-10-2019 - |
Вопрос
В C.1.3 IS C ++ (2003 г. Он также присутствует в IS C ++ 11) стандарт указывает на разницу между ISO C и C ++;а именно для
родовое слово sizeof(0, arr)
возвращает код сгенерированного кода на C, но сгенерирует код кода на С ++.
Я не могу найти документации для кода sizeof(char*)
с двумя аргументами.Очевидной альтернативой является оператор запятой, но я так не думаю: 100
в C - это sizeof
;sizeof(arr)
- это 100
.И sizeof(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
без скобок, поскольку это не вызов функции, а если я помещаю скобки, это потому, что они нужны для следующего выражения.