Undefined ссылка на глобальную переменную во время связывания

Я пытаюсь скомпилировать программу, которая разделена на 3 модуля, соответствующих трем исходным файлам: a.c, b.c и z.c. z.c содержит функцию main(), которая вызывает функции в a.c и b.c. Кроме того, функция в a.c вызывает функцию в b.c и наоборот. Наконец, существует глобальная переменная count, которая используется тремя модулями и определяется в отдельном файле заголовка, global.h.

Код исходных файлов следующий:

a.c

#include "global.h"
#include "b.h"
#include "a.h"

int functAb() {
    functB();
    functA();
    return 0;
}

int functA() {
    count++;
    printf("A:%d\n", count);
    return 0;
}

b.c

#include "global.h"
#include "a.h"
#include "b.h"

int functBa() {
    functA();
    functB();
    return 0;
}

int functB() {
    count++;
    printf("B:%d\n", count);
    return 0;
}

z.c

#include "a.h"
#include "b.h"
#include "global.h"

int main() {
    count = 0;
    functAb();
    functBa();
    return 0;
}

Файлы заголовков:

a.h

#ifndef A_H
#define A_H

#include <stdio.h>

int functA();
int functAb();

#endif

b.h

#ifndef B_H
#define B_H

#include <stdio.h>

int functB();
int functBa();

#endif

global.h

#ifndef GLOBAL_H
#define GLOBAL_H

extern int count;

#endif

И, наконец, makefile, который воспроизводит мою ошибку:

CC = gcc
CFLAGS = -O3 -march=native -Wall -Wno-unused-result

z:  a.o b.o z.o global.h
    $(CC) -o z a.o b.o z.o $(CFLAGS)
a.o:    a.c b.h global.h
    $(CC) -c a.c $(CFLAGS)
b.o:    b.c a.h global.h
    $(CC) -c b.c $(CFLAGS)
z.o:    z.c a.h global.h
    $(CC) -c z.c $(CFLAGS)

С этим я могу скомпилировать объекты a.o, b.o и z.o в порядке, но при связывании с make z я получаю undefined reference to 'count' во всех них:

z.o: In function `main':
z.c:(.text.startup+0x8): undefined reference to `count'
a.o: In function `functAb':
a.c:(.text+0xd): undefined reference to `count'
a.c:(.text+0x22): undefined reference to `count'
a.o: In function `functA':
a.c:(.text+0x46): undefined reference to `count'
a.c:(.text+0x5b): undefined reference to `count'
b.o:b.c:(.text+0xd): more undefined references to `count' follow
collect2: ld returned 1 exit status

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

Ответ 1

Измените z.c на

#include "a.h"
#include "b.h"
#include "global.h"

int count; /* Definition here */
int main() {
    count = 0;
    functAb();
    functBa();
    return 0;
}

Из global.h все ваши файлы наследуют объявление переменной count, но определение отсутствует во всех файлах.

Вы должны добавить определение в один из файлов как int count = some_value;

Ответ 2

Вы указали счетчик, но не определили его.

extern является частью объявления, а не определением.

Чтобы быть явным, extern является спецификатором класса хранения и используется при объявлении.

Вам нужно определить int count где-то в ваших исходных файлах.

Ответ 3

Вам нужно добавить int count; в ваш z.c файл. Это из-за объявления переменной в файле заголовка как extern сообщает компилятору, что переменная будет объявлена ​​в другом файле, но переменная еще не объявлена ​​и будет разрешена b компоновщиком.

Затем вам нужно где-то объявить переменную.