Инициализация статической переменной в заголовке

Я новичок в программировании на C, поэтому я стараюсь много разных вещей, чтобы попробовать и ознакомиться с языком.

Я написал следующее:

Файл q7a.h:

static int err_code = 3;
void printErrCode(void);

Файл q7a.c:

#include <stdio.h>
#include "q7a.h"

void printErrCode(void)
{
        printf ("%d\n", err_code);
}

Файл q7main.c:

#include "q7a.h"

int main(void)
{
        err_code = 5;
        printErrCode();

        return 0;
}

Затем я запустил следующее в make файле (я использую ОС Linux)

gcc –Wall –c q7a.c –o q7a.o
gcc –Wall –c q7main.c –o q7main.o
gcc q7main.o q7a.o –o q7

выход равен 3.

Почему это происходит?

Если вы инициализируете статическую переменную (фактически любую переменную) в файле заголовка, поэтому, если 2 файла содержат один и тот же заголовочный файл (в этом случае q7.c и q7main.c), компоновщик предназначен для получения ошибки для определяя дважды тот же var?

И почему значение 5 не вставлено в статический var (ведь оно статично и глобально)?

Спасибо за помощь.

Ответ 1

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

Вместо этого вы можете рассмотреть extern int и выбрать один .c файл, который фактически определяет его (т.е. просто int err_code=3).

Ответ 2

Статические переменные donot имеют внешнюю связь, что означает, что они не могут быть доступны за пределами единицы перевода, в которой они определены. Таким образом, в вашем случае, когда q7.h является # include'ed в обоих единицах перевода q7a.c и q7main.c... в их соответствующих файлах .o есть две разные копии. Вот почему компоновщик не сообщает об ошибке, потому что обе копии не видны компоновщиком при выполнении внешней привязки символов.

Ответ 3

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

Когда вы печатаете err_code непосредственно в функции Main, вы увидите его значение как 5 вместо 3, но вы вызываете функцию printErrCode, которая определена в другом файле "q7a.c", для которого err_code имеет другое расположение в памяти в котором объем памяти err_code все еще равен 3, и он не обновляется, и поэтому вы получаете значение как 3 вместо 5.

Поскольку создается две памяти, а err_code рассматривается как две разные переменные, имеющие разную память с разным объемом файла, вы не увидите никаких ошибок компоновки.

Ответ 4

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

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

Статическая переменная должна быть объявлена ​​в файле, в котором мы ее используем, не должна отображаться в файле заголовка.

Надеюсь, что я даю правильную информацию. Если я ошибаюсь, не стесняйтесь исправлять мои высказывания в ваших комментариях.