Не могу скомпилировать с переменной void в C - PullRequest
4 голосов
/ 30 июля 2011

test.c

int main () {
   void a;
   return 0;
}

Я использую gcc для компиляции, но выдает ошибку:

ошибка: переменная или поле 'a' объявлено недействительным

Из того, что я прочитал здесь , Я думал, что могу объявить переменную void без проблем.

Ответы [ 4 ]

8 голосов
/ 30 июля 2011

Как указывается в вашей ссылке:

Переменная, которая сама объявлена ​​как void (например, my_variable выше), бесполезна; ему не может быть присвоено значение, он не может быть приведен к другому типу, фактически не может использоваться каким-либо образом.

Это означает, что, хотя синтаксически правильное, объявление void ни к чему не полезно, именно поэтому GCC может считать его ошибкой. Даже если он скомпилируется, вы не сможете ничего сделать с переменной, поэтому я думаю, что ваш вопрос связан только с проверкой этого поведения.

На самом деле void полезен только тогда, когда мы говорим об указателях (void*), поскольку он позволяет объявлять универсальный указатель без указания типа.

5 голосов
/ 30 июля 2011

Нет, но вы можете объявить пустой указатель: void *. void * может содержать любой указатель объекта.

void * гарантированно содержит только указатели объекта (то есть данных)

[но]

преобразование указателя функции в тип void непереносимо *

1 голос
/ 30 июля 2011

Хотя в книге говорится, что void a; является действительным утверждением, я не верю, что оно когда-либо соответствовало стандартам. При этом первое издание книги было выпущено в 1987 году, поэтому оно также может быть перенесено из более старых реализаций GCC.

0 голосов
/ 08 апреля 2017

void *x; является допустимым оператором.

void x; не является допустимым оператором.

Функция, которая возвращает указатель на void, также является допустимой.

Почему это так?

Когда переменная объявлена ​​в функции, компилятор должен выделить пространство памяти для переменной.Но когда переменная имеет тип void, компилятор не знает, сколько байтов выделено для этой переменной.Так что это не будет работать для компилятора.Однако указатель на void отличается.Указатель может иметь тип void, который может быть прочитан как int, или double, или как float, или short или char во время чтения.В этом случае требуется явное приведение типов или автоматическое продвижение типов, выполняемое компилятором.

например,

int
function_A( void *x )
{
    int *p = (int *)x; 
    return *p;
}

double
function_B( void *x )
{
    double *p = (double *)x; 
    return *p;
}

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

double
function_B( void *x )
{
    return (double)*x; 
}

Концептуально, это имеет смысл.Но С не позволяет этого.

...