Может ли быть тип C ++, который занимает 0 байтов - PullRequest
6 голосов
/ 25 ноября 2011

Я пытаюсь объявить переменную C ++, которая занимает ноль байтов. Он в объединении, и я начал с типа int [0]. Я не знаю, действительно ли это нулевые байты (хотя sizeof (int [0]) было 0). Мне нужен лучший способ объявить 0-байтовый тип, и, надеюсь, тот, который может быть определен как что-то вроде nullType или emptyType. Переменная находится в объединении, поэтому в конце концов память зарезервирована в любом случае. Я попытался void на случай, что это будет работать, но C ++ жаловался. Я использую Ubuntu 10.10, с текущей версией ядра и современным GCC. Вот союз:

union RandomArgumentTypesFirst
{
    uint uintVal;
    nullType nullVal;
}

А вот тип определения:

typedef int[0] nullType;

Компилятор говорит это о typedef:

error: variable or field ‘nullVal’ declared voidmake[2]:

Когда я набрал int[0], это сработало. Есть предложения?

EDIT: Как сказал @fefe в комментариях, компилятор может предоставить int[0] в качестве расширения. На сайте GCC сказано, что компилятор имеет много расширений по умолчанию.

Ответы [ 6 ]

6 голосов
/ 25 ноября 2011

Стандарт явно запрещает существование экземпляра типа с размером 0, причина в том, что если объект может иметь размер 0, то два разных объекта могут быть расположены по одному и тому же адресу.Например, пустая структура будет вынуждена иметь размер> 0, чтобы соответствовать этому требованию, даже если компилятор может использовать ее как размер другого типа, размер == 0.

* 1002это то, что вы хотите сделать с пустым классом ?
6 голосов
/ 25 ноября 2011

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

class Empty {};

... приведет к истине:

Empty emp;
assert( sizeof(emp) != 0 );

Причина этого в том, что вы можете взять адрес объекта.

РЕДАКТИРОВАТЬ: я первоначально сказал, что sizeof будет 1, но согласно комментарию @Als, я нашел соответствующий отрывок в Стандарте, и он действительно просто ненулевой:

[Классы] §9 / 3

Полные объекты и дочерние подобъекты типа класса должны иметь ненулевой размер

5 голосов
/ 25 ноября 2011

typedef написано с ошибкой:

typedef int nullType[0];

Как уже отмечали другие, вы не можете иметь объект размером 0;Однако компиляторы могут (и часто делают) обеспечить оптимизацию Empty Base Class.

1 голос
/ 25 ноября 2011

Переменная в C ++ никогда не может принимать ноль байтов. Каждый объект должен иметь уникальный адрес, что невозможно, если его размер равен нулю.

Кстати, int[0] недопустимо в стандарте C ++. Если вы используете GCC, скомпилируйте его с параметром -pedantic, вы получите следующее предупреждение:

warning: ISO C++ forbids zero-size array 'x' [-pedantic]

Кроме того, синтаксис для typedef должен быть таким:

  typedef int array[100]; //zero cannot be size - illegal!
0 голосов
/ 20 июля 2016

Звучит так, как вы хотите std :: необязательно .
У него не будет sizeof 0, но это не важно для выражения пустого значения.


В соответствующей заметке есть предложение C ++ ( P0146R1 ) сделать void регулярным типом.
Далее в статье обсуждается, почему даже sizeof(void) не может быть 0.

Почему sizeof (void) не равен 0?

Одно из предложений, которое неоднократно выдвигалось, это иметь sizeof (void) сообщить 0 и разрешить нескольким экземплярам использовать один и тот же адрес. Это не позволит пользователям использовать трюки, похожие на пустые базовая оптимизация для более оптимального использования памяти. В идеале это было бы так, однако такое изменение языка и обширна, и выходит за рамки предложения. Разрешение типу иметь размером 0 и для разрешения совместного использования адресов отдельными экземплярами подразумевается радикальные и неуловимые изменения в существующем коде . Например, если Вы должны были сделать массив такого типа void, указатель, по крайней мере, в традиционный смысл, больше не сможет быть использован в качестве итератор в этот массив (в частности, это означает, что общий код, который полагается на то, что теперь не получится для такого типа размера 0). Как хорошо, любой код, который полагается на тип объекта и адрес как уникальный, потерпит неудачу для пустых типов, хотя в остальном это совершенно приемлемо. Наконец, если такой размер был разрешен для void, это действительно должно быть разрешено для любого типа, в том числе пользовательских типов. Имея специальный Правило для пустоты сделало бы еще одну вещь, чтобы думать и по-разному для пустых типов. Вместо этого это предложение выбирает оставить размер пустоты неуказанным и тем самым регулировать существующие языковые правила. На практике ожидается, что пустота, скорее всего, будет размер 1 в большинстве реализаций, хотя это не обязательно. Если возможное изменение было сделано в языке, чтобы учесть типы размера 0, тогда void сможет безоговорочно воспользоваться этим.


Хотя этот вопрос предназначен для C ++, следует отметить, что пустая структура в C может привести к sizeof из 0. Это, однако, неопределенное поведение.

Если список объявляемых структур не содержит именованных членов, поведение не определено.

0 голосов
/ 25 ноября 2011

Стандарт C ++ явно требует, чтобы каждый тип имел размер как минимум 1. Это тесно связано с требованием, чтобы каждый объект имел уникальный адрес (рассмотрим Foo x[10], если Foo имел нулевой размер).

...