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

Что даст этот оператор?

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

Изменить: расширение вопроса.

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

Ответ 1

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

void n;

ИЗМЕНИТЬ. К моему удивлению, выполнение sizeof(void) действительно компилируется в GNU C:

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

Однако в С++ это не так:

$ 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

Ответ 2

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

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

Ответ 3

Хотя void может стоять на месте для типа, он фактически не может удерживать значение. Поэтому он не имеет размера в памяти. Получение размера void не определено.

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

Ответ 5

void не имеет размера. В C и С++ выражение sizeof (void) недействительно.

В C, цитируя N1570 6.5.3.4, пункт 1:

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

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

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

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

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

Ответ 6

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

Ответ 7

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

В С++ я получаю:

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

Ответ 8

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

Ответ 9

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

например.

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

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

Ответ 10

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

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

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

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

struct Empty {
} empty;

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

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

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