Можно изменить размер 0 (ноль)

Возможно ли, чтобы оператор 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