Каков размер пустоты?


что бы это заявление даст?

void * p = (void*) malloc(sizeof(void));

Edit: расширение к вопросу.

Если sizeof (void) дает 1 в компиляторе GCC, то выделяется 1 байт памяти и указатель p указывает на этот байт и будет ли P++ увеличен до 0x2346? Предположим, что p равно 0x2345. Я говорю о p, а не *p.

10 61

10 ответов:

тип void не имеет размера; это было бы ошибкой компиляции. По той же причине вы не можете сделать что-то вроде:

void n;

правка. К моему удивлению, делаю sizeof(void) на самом деле тут компиляция в GNU C:

$ echo 'int main() { printf("%d", sizeof(void)); }' | gcc -xc -w - && ./a.out 
1

однако, в C++ это не:

$ echo 'int main() { printf("%d", sizeof(void)); }' | gcc -xc++ -w - && ./a.out 
<stdin>: In function 'int main()':
<stdin>:1: error: invalid application of 'sizeof' to a void type
<stdin>:1: error: 'printf' was not declared in this scope

Если вы используете GCC и не используете флаги компиляции, которые удаляют определенные расширения компилятора, то sizeof(void) Это 1. GCC имеет нестандартное расширение что делает.

В общем, void является неполным типом, и вы не можете использовать sizeof для неполных типов.

хотя void может стоять на месте, для вида, он не может вообще иметь значение. Поэтому он не имеет размера в памяти. Получение размера void Не определен.

A voidуказатель это просто языковая конструкция, означающая указатель на untyped память.

принимая размер пустоты является расширение GCC.

void не имеет размера. Как в C, так и в C++ выражение sizeof (void) является недействительным.

в C, цитирую N1570 6.5.3.4 пункт 1:

The sizeof оператор не должен применяться к выражению, которое имеет тип функции или неполный тип в скобках имя такой тип или выражение, которое обозначает элемент битового поля.

(N1570-проект 2011 года Стандарт ISO C.)

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

стандарт C++ 11 имеет очень похожую формулировку. Оба издания были опубликованы после того, как был задан этот вопрос, но правила восходят к стандарту ANSI C 1989 года и самым ранним стандартам C++. На самом деле, правило, что void неполный тип, к которому sizeof не может быть применен возвращается точно так же, как введение void на язык.

gcc имеет расширение что относится к sizeof (void) как 1. gcc по умолчанию не является соответствующим компилятором C, поэтому в своем режиме по умолчанию он не предупреждает о sizeof (void). Такие расширения разрешены даже для полностью соответствующих компиляторов C, но диагностика по-прежнему требуется.

sizeof() не может применяться к неполным типам. И void является неполным типом, который не может быть завершен.

В C,sizeof(void) == 1 в GCC, но это, кажется, зависит от вашего компилятора.

В C++, я получаю:

In function 'int main()':
Line 2: error: invalid application of 'sizeof' to a void type
compilation terminated due to -Wfatal-errors.

к 2-й части вопроса: обратите внимание, что sizeof (void *)!= sizeof (void). На 32-разрядной арке sizeof (void *) составляет 4 байта, поэтому p++ будет установлен соответствующим образом.Величина, на которую увеличивается указатель, зависит от данных, на которые он указывает. Таким образом, он будет увеличен на 1 байт.

хотя sizeof (void), возможно, не имеет смысла сам по себе, это важно, когда вы делаете любую математику указателя.

например.

 void *p;
 while(...)
      p++;

Если sizeof (void) считается 1, то это будет работать. Если sizeof (void) считается 0, то вы попали в бесконечный цикл.

большинство компиляторов C++ выбрали, чтобы вызвать ошибку компиляции при попытке получить sizeof(void).

при компиляции C gcc не соответствует и решил определить sizeof(void) как 1. Это может показаться странным, но имеет свое обоснование. При выполнении арифметики указателя добавление или удаление одной единицы означает добавление или удаление объекта, указанного на размер. Таким образом, определение sizeof(void) как 1 помогает определение void* как указатель на байт (нетипизированный адреса памяти). В противном случае у вас будет удивительное поведение с помощью указателя арифметика вроде p+1 == p when п void*. Такая арифметика указателей на указатели void не допускается в c++, но отлично работает при компиляции C с помощью gcc.

стандартный рекомендуемый способ будет использовать char* для такого рода целей (указатель на байт).

другое аналогичное различие между C и C++ при использовании sizeof возникает, когда вы определили пустую структуру, например:

struct Empty {
} empty;

использование gcc в качестве моего компилятора C sizeof(empty) возвращает 0. Используя g++ тот же код будет возвращение 1.

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

но это просто избегает удивительного поведения (угловой случай сравнения ссылок) путем введения другого (пустые объекты, даже стручки потребляют не менее 1 байта памяти).