Подтвердить что ты не робот

Назначение члена структуры, вызывая синтаксическую ошибку, если не внутри функции

Я хочу назначить определенное значение глобальной переменной (определяемой пользователем) на языке программирования C. Когда я делаю это из любой другой функции или основной, это нормально. Но когда я делаю это из глобального пространства (вне любой функции), он дает следующую ошибку компиляции:

[expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘.’ token]

Ниже приведен фрагмент кода, вызывающий проблему:

#include <stdio.h>
#define MAX_SIZE 5

typedef struct
{
    int val[MAX_SIZE];
    int top;
}stack_t;

stack_t s;
s.top = -1;  // <== Initialization from here is causing compilation error

main()
{
    //s.top = -1; < === Initialization from here is fine  
    printf("s.top =%d\n", s.top);
    return 0;
}

Но такое же назначение для целых переменных не дает только предупреждения

#include <stdio.h>

int i,j,k,l;
k=10;
main()
{
        printf("i= %d, j=%d k=%d l=%d\n", i, j, k, l);
        return 0;
}

Может кто-нибудь объяснить причину этого?

4b9b3361

Ответ 1

Ошибка от назначения s.top не вызывает удивления. Это не инициализация, а назначение, а в C. это разные понятия. У вас не может быть назначений вне функций.

Интересная часть здесь состоит в том, что похоже, что вы можете выполнить назначение целочисленной переменной k. Но это иллюзия, поскольку в этом случае это не назначение, а инициализация!

Линия

k = 10;

интерпретируется не как назначение, а как определение переменной. Подсказка к этому заключается в том, что GCC дает предупреждения "определение данных не имеет типа или класса хранения" и "по умолчанию по умолчанию" int "в объявлении" k ". Таким образом, строка может быть записана как

int k = 10;

Как писал Мэтт в комментарии ниже, исключая тип данных, подобный этому, похоже, является расширением GCC, а не тем, что позволяет стандарт.

(Кстати, включите предупреждения в своем компиляторе и обратите внимание на них!)

Но подождите, не было ли уже определения k в строке выше, и вы не можете иметь более одного определения, можете ли вы?

Во-первых, помните, что C делает различие между определениями и декларациями. Определение переменной - это когда вы "создаете" переменную и необязательно даете ей начальное значение. Объявление - это когда вы просто указываете компилятору, что переменная существует, а также ее имя и тип данных, но определение находится в другом месте. У вас может быть как определение, так и одно или несколько объявлений одной и той же переменной. Например:

int xxx = 10; // This is the definition of xxx
int xxx; // This is a declaration of xxx
int xxx; // Another delaration of xxx

Но иногда компилятор не может определить, является ли то, что он видит, объявлением или определением, а затем оно интерпретируется как "предварительное определение" или, другими словами, "возможно, определение, возможно просто объявление, решим позже". Например:

int yyy;

Является ли это определение переменной yyy (без начального значения), или это просто объявление, где определение будет найдено в другом месте? Компилятор не знает, поэтому он ждет решения и называет это предварительным определением.

Когда компилятор видит ваше первое объявление k (наряду с другими переменными i, j и l), оно интерпретируется как предварительное определение, и когда будет найдено более позднее определение, то предварительное определение k будет принято объявление, а не определение.

Ответ 2

Код C должен находиться внутри функции. Вы можете объявить глобальную внешнюю функцию, но вы не можете написать оператор присваивания вне функции. То есть вы можете установить начальное значение как часть объявления структуры, но вы не можете ее изменить. Здесь ваша декларация - это только "stack_t s;" линия.

Все в C заканчивается компиляцией символов в двоичном формате (примером может быть формат ELF). У символов есть имена, поэтому функции называются кусками кода, а глобальные имена называются кусками данных. В скомпилированном двоичном файле нет "свободных плавающих" кусков, все должно идти под именем.

В модели C код, плавающий вне функции, не имеет смысла, поскольку у C нет места, где он будет запускать этот код. C никогда не запускает файл так, как это делает bash или Python или javascript; он запускает только двоичные файлы. Таким образом, он запускается только с именем функции. Файлы известны только во время компиляции, а не во время выполнения.

Ответ 3

Инициализация внешней стороны main является причиной этой ошибки. Вы можете сделать это, используя это.

stack_t s={.top=-1};

Это позволит вам выполнить инициализацию при объявлении. Отправьте ссылку или здесь Это может быть полезно.

Ответ 4

Существуют различия между назначением и инициализацией. Следует отметить, что назначение не может выполняться вне функции. Утверждение

s.top = -1;  

- это присвоение, а не инициализация.

C99 и последний предоставляет обозначенную инициализацию структур и массивов. Таким образом, вы можете инициализировать только член top структуры s как

stack_t s = { .top = -1 };   

и другие члены будут инициализированы компилятором 0.

Ответ 5

В глобальном пространстве вы можете только инициализировать и объявлять переменные, но не можете присваивать значение переменным. В вашем коде вы назначаете значение члену структуры, поэтому его ошибка бросания и то же самое верно для целых чисел для вашего кода ниже.

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

typedef struct 
{
     int val[MAX_SIZE];
     int top;
}stack_t;

stack_t s={{},-1};

main()
{
    printf("s.top=%d",s.top);
    return 0;
}