Чому sizeof int неправильний, а sizeof (int) правильний?


96

Ми знаємо, що sizeofце оператор, який використовується для обчислення розміру будь-якого типу даних та виразу, і коли операнд є виразом, дужки можна опустити.

int main()
{
        int a;

        sizeof int;
        sizeof( int );
        sizeof a;
        sizeof( a );

        return 0;
}

перше використання sizeofнеправильно, тоді як інші мають рацію.

Коли він компілюється за допомогою gcc, буде видано таке повідомлення про помилку:

main.c:5:9: error: expected expression before int

Моє питання полягає в тому, чому стандарт C не дозволяє такого роду операції. Викличе sizeof intбудь-яку неясність?


5
Найсмішніше те, що не всі вирази приймаються без дужок: спробуйте sizeof (int)a.
Fred Foo

2
@MikkelK .: OP запитує міркування за стандартними цитатами, які йому вже відомі цитати, згадані у позначеній відповіді.
Алок Зберегти

2
@Lundin: sizeof +(int)aмає перевагу перед тим, *&як насправді компілювати ;-)
Steve Jessop

2
@SteveJessop Ах, правильно, це не значення. Хоча він і скомпілювався в Embarcadero C ++, як не дивно. У будь-якому випадку, я вважаю, що ми щойно знайшли застосування для оператора unary +! Це, мабуть, перший раз в історії програмування на С :)
Лундін,

2
@Lundin: Ти все одно повинен бути обережним з одинарним +. Наприклад, sizeof +(char)a == sizeof(int)через цілочисельне просування, мабуть, менше схильних до помилок просто вставляти в дужки, якщо взагалі виникає занепокоєння щодо виразу, розмір якого ви намагаєтеся прийняти. Тож я не впевнений, що зайшов би так далеко, що назвав це "використанням", хоча, зізнаюся, я це і використовував ...
Стів Джессоп,

Відповіді:


101

Наступне може бути неоднозначним:

sizeof int * + 1

Це що (sizeof (int*)) + 1, чи (sizeof(int)) * (+1)?

Очевидно, що мова C могла запровадити правило для вирішення двозначності, але я можу уявити, чому це не заважало. З мовою, якою вона є, специфікатор типу ніколи не виглядає "оголеним" у виразі, і тому немає необхідності в правилах, щоб визначати, чи є ця секунда *частиною типу або арифметичним оператором.

Існуюча граматика вже вирішує потенційну двозначність sizeof (int *) + 1. Це так (sizeof(int*))+1, ні sizeof((int*)(+1)) .

C ++ має дещо подібну проблему для вирішення за допомогою синтаксису приведення в стилі функції. Ти можеш писати int(0)і ти можеш писати typedef int *intptr; intptr(0);, але ти не можеш писати int*(0). У такому випадку дозвіл полягає в тому, що "голий" тип повинен бути простим ім'ям типу, це не може бути просто будь-який старий ідентифікатор типу, який може мати пробіли, або кінцеві знаки пунктуації. Можливо, це sizeofмогло бути визначено з тим самим обмеженням, я не впевнений.


1
У C ++ є new int*(X)неоднозначне, якщо C ++ не вказує, що новий оператор бере найдовший рядок, який може бути типом. Отже, в C ++ вони могли б зробити те саме з sizeof, я думаю. Але в C ++ ви можете сказати, sizeof int()що тоді було б неоднозначним (тип або значення, ініціалізоване int?).
Йоханнес Шауб - Litb

@ JohannesSchaub-litb: М-м-м, тож, можливо, тоді C ++ міг би сказати, що тип є кращим, якщо його можна проаналізувати, інакше це вираз. Неоднозначність буде вирішена , але sizeof int()буде погано сформована ( «Не operator()для size_t"), який я очікував би небажано!
Steve Jessop

32

З C99 Standard

6.5.3.4.2 оператор дає розмір (в байтах) свого операнда, який може бути вираз в дужках або ім'я типу.
sizeof

У вашому випадку intце не вираз, ані назва в дужках.


10
Я не розумію, чому це отримує 7 голосів проти. Як і три видалені відповіді, він просто повторює правило, а не пояснює, чому правило існує.
Fred Foo

7
@larsmans, так, я з вами згоден. Хоча воно продовжує повторювати правило, але, принаймні, воно дає шматок дозволу на читання.
Yishu Fang

3
@larsmans Якщо ми почнемо намагатися виправдати кожне рішення, прийняте в C99, ми будемо тут увесь рік. Посилання на стандарт є настільки ж хорошим способом, як завершити цю дискусію.
Перрі,

1
@Perry: якщо вам не подобається таке запитання, ви можете проголосувати, щоб закрити питання як аргументоване.
Fred Foo

4
Як непрактикуючий C ++, навіть я розумію цю відповідь, не впевнений, у чому проблема, якщо ти вмієш читати та розуміти англійську мову.
Kev

6

Існує два способи використання оператора sizeof у C. Синтаксис такий:

C11 6.5.3 Unary operators
...
sizeof unary-expression
sizeof ( type-name )

Кожного разу, коли ви використовуєте тип як операнд, ви повинні мати дужки відповідно до синтаксичного визначення мови. Якщо ви використовуєте sizeof для виразу, вам не потрібні дужки.

Стандарт C дає один із таких прикладів того, де ви можете використовувати його у виразі:

sizeof array / sizeof array[0]

Однак задля послідовності та уникнення помилок, пов'язаних з перевагою оператора, я особисто радив би завжди використовувати () незалежно від ситуації.


@ JohannesSchaub-litb Я погоджуюсь, що це не дає обгрунтування того, як аргументував комітет стандарту C, коли вони вказали стандарт C90. Вам доведеться їх запитати ... Він відповідає без будь-яких обґрунтувань, однак C не дозволяє, оскільки синтаксис відповідає зазначеному в 6.5.3. ОП також, здавалося, не знав про різницю між sizeof expressionта sizeof(type), що пояснюється у цій відповіді.
Лундін,

(Для протоколу я щойно прочитав обґрунтування C90 та C11, і жодне з них не дає жодних пояснень.)
Лундін,

Я підозрюю, що для цього немає необхідного обґрунтування, це просто те, як оригінальні дизайнери C вирішили це зробити. Можливо, це полегшило процес раннього аналізатора. Я збирався опублікувати відповідь про те, що typedefs та змінні мають однаковий простір імен, але це не виключає дозволу на перший синтаксис; йому просто потрібні правила синтаксичного аналізу, щоб сказати, що вона віддає перевагу змінній, коли немає паренів, віддає перевагу типу, коли вони є, і будь-яку форму можна використовувати, коли назва однозначна. Оскільки немає потреби його змінювати, комітети зі стандартів залишили це в спокої.
Бармар,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.