Возможно ли, чтобы оператор sizeof когда-либо возвращал 0 (ноль) в C или С++? Если это возможно, правильно ли это с точки зрения стандартов?
Ответ 1
В С++ пустой класс или структура имеет sizeof
не менее 1 по определению. Из стандарта С++ 9/3 "Классы": "Завершенные объекты и субобъекты членов типа класса должны иметь ненулевой размер".
В C пустая структура не разрешена, за исключением расширения (или недостатка в компиляторе).
Это следствие грамматики (которая требует наличия чего-то внутри фигурных скобок) вместе с этим предложением из 6.7.2.1/7 "Спецификаторы структуры и объединения": "Если в списке struct-declaration-list нет именованных членов, поведение undefined".
Если разрешена структура нулевого размера, то это расширение языка (или недостаток в компиляторе). Например, в GCC расширение документировано в "Структуры без членов" , в котором говорится:
GCC разрешает структуре C не иметь членов:
struct empty { };
Структура будет иметь нулевой размер. В С++ пустые структуры являются частью языка. g++ обрабатывает пустые структуры, как если бы у них был единственный член типа
char
.
Ответ 2
sizeof
никогда не возвращает 0
в C и на С++. Каждый раз, когда вы видите sizeof
, оценивая 0
, это ошибка/сбой/расширение конкретного компилятора, который не имеет никакого отношения к языку.
Ответ 3
Каждый объект в C должен иметь уникальный адрес. Другими словами, адрес должен содержать не более одного объекта данного типа (для того, чтобы разыменовать указатель для работы). При этом рассмотрим "пустую" структуру:
struct emptyStruct {};
и, более конкретно, массив из них:
struct emptyStruct array[10];
struct emptyStruct* ptr = &array[0];
Если объекты действительно пусты (то есть, если sizeof(struct emptyStruct) == 0
), то ptr++ ==> (void*)ptr + sizeof(struct emptyStruct) ==> ptr
, что не имеет смысла. Какой объект будет *ptr
, тогда обратитесь к ptr[0]
или ptr[1]
?
Даже если структура не имеет содержимого, компилятор должен обрабатывать ее так, как если бы она составляла один байт, чтобы поддерживать принцип "один адрес, один объект".
Спецификация языка C (раздел A7.4.8) указывает это требование как
когда применяется к структуре или объединению, результат (оператора
sizeof
) - количество байтов в объекте, включая любые отступы, необходимые для объект разбивает массив
Поскольку байт заполнения должен быть добавлен к "пустым" объекту, чтобы он работал в массиве, sizeof()
должен поэтому возвращать значение по крайней мере 1 для любого допустимого ввода.
Edit:
Раздел A8.3 спецификации C вызывает структуру без списка членов неполного типа, а определение sizeof
конкретно указывает (с добавлением акцента):
Оператор (sizeof) может не быть применяется к операнду функции тип или неполного типа, или битовое поле.
Это означало бы, что использование sizeof
в пустой структуре было бы столь же недействительным, как использование его по типу данных, который не был определен. Если ваш компилятор разрешает использование пустых структур, имейте в виду, что использование sizeof
на них не допускается в соответствии с спецификацией C. Если ваш компилятор позволяет вам это сделать, поймите, что это нестандартное поведение, которое не будет работать на всех компиляторах; не полагайтесь на это поведение.
Изменить: Смотрите также эту запись в FAQ Bjarne Stroustrup.
Ответ 4
Пустое строение, так как isbadawi упоминает. Также gcc позволяет массивы размером 0:
int a[0];
sizeof(a);
EDIT: увидев ссылку MSDN, я попробовал пустую структуру в VS2005, а sizeof вернул 1. Я не уверен, что это ошибка VS или если спецификация настолько гибкая в отношении такого рода вещей
Ответ 5
на мой взгляд, лучше, что sizeof возвращает 0 для структуры размера 0 (в духе с). но тогда программист должен быть осторожным, когда берет sizeof пустой структуры.
но это может вызвать проблему. когда массив таких структур определен, то
& arr [1] == & arr [2] == & arr [0]
что заставляет их потерять свои тождества.
Я думаю, это напрямую не отвечает на ваш вопрос, возможно ли это или нет. хорошо, что может быть возможно в зависимости от компилятора. (как сказано в ответе Майкла выше).
Ответ 6
typedef struct {
int : 0;
} x;
x x1;
x x2;
В MSVC 2010 (/Za/Wall):
sizeof(x) == 4
&x1 != &x2
В GCC (-ansi -pedantic -Wall):
sizeof(x) == 0
&x1 != &x2
то есть. Хотя в GCC он имеет нулевой размер, экземпляры структуры имеют разные адреса.
ANSI C (C89 и C99 - я не смотрел на С++) говорит: "Можно однозначно выразить адрес каждого отдельного байта объекта". Это кажется неоднозначным в случае объекта с нулевым размером, поскольку он, возможно, не имеет байтов.
Изменить: "Объявление битового поля без декларатора, но только двоеточие и ширина, указывает на неназванное битовое поле. В качестве особого случая это бит-поле с шириной 0 указывает на то, что дальше бит-поле должно быть упаковано в блок, в котором было размещено предыдущее бит-поле, если оно есть."
Ответ 7
Я думаю, что он никогда не возвращает 0 в c, пустые структуры не разрешены
Ответ 8
Здесь тест, где sizeof дает 0
#include <stdio.h>
void func(int i)
{
int vla[i];
printf ("%u\n",(unsigned)sizeof vla);
}
int main(void)
{
func(0);
return 0;
}
Ответ 9
Если у вас есть это:
struct Foo {};
struct Bar { Foo v[]; }
g++ -ansi
возвращает sizeof (Bar) == 0. Как и компилятор clang и intel.
Однако это не компилируется с помощью gcc. Я вывел его на расширение С++.
Ответ 10
struct Empty {
} em;
struct Zero {
Empty a[0];
} zr;
printf("em=%d\n", sizeof(em));
printf("zr=%d\n", sizeof(zr));
Результат:
em=1
zr=0