Существует несколько определений переменной, но компоновщик не создает ошибок на моем компьютере. - PullRequest
0 голосов
/ 02 августа 2020

В моем текущем проекте я инициализирую окно для рисования. Я использую указатель на функцию для инициализации с нескольких платформ. Поэтому мне действительно нужен только один экземпляр указателя на функцию window_init.

Я заметил, что забыл пометить этот указатель на функцию как extern в моем файле заголовка и определил его второй раз в моем C файле, чтобы дать это хранилище.

Заголовок включен в несколько файлов, поэтому, насколько я понимаю, должен генерировать ошибку компоновщика. Я тестировал это на своем ноутбуке, и на самом деле он генерировал ошибку компоновщика. Почему мой рабочий стол не выдает ошибок / как узнать? В обоих случаях я использовал mingw64 с cmake в Clion для сборки, используя -Wall -Wextra -pedantic -Werror.

Итак, для ясности: мой рабочий стол работает нормально, мой ноутбук выдает ошибки компоновщика. Я ожидаю ошибок компоновщика на обеих машинах, и я хочу выяснить, почему этого не происходит.

Решение, конечно, состоит в использовании extern, а затем он строится на обеих машинах, однако я хочу знать, что происходит on.

Вот минимальный пример, который также отлично работает на моем рабочем столе, хотя я бы ожидал, что он потерпит неудачу:

window.h

#ifndef CEXTERNTETS_WINDOW_H
#define CEXTERNTETS_WINDOW_H

void window_functions_init();

void(*window_init)(); //This is the first definition and should be marked as extern to my understanding if I want to give it storage in my c file

#endif //CEXTERNTETS_WINDOW_H

окно. c

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


void(*window_init)(); //This is the second definition

void window_init_implementation()
{
    printf("window_init_implementation\n");
}


void window_functions_init()
{
    window_init = &window_functions_init;
}

второе включение (мне нужно включить window.h в несколько файлов, поэтому я добавил его сюда и добавил функция, чтобы компилятор не мог оптимизировать его)

#ifndef CEXTERNTETS_SECOND_INCLUDE_H
#define CEXTERNTETS_SECOND_INCLUDE_H

#include "window.h"

void doit()
{
    printf("doit");
}

#endif //CEXTERNTETS_SECOND_INCLUDE_H

main. c

#include <stdio.h>
#include "window.h"
#include "second_include.h"

int main() {
    window_functions_init();
    window_init();
    doit();

    printf("Hello, World!\n");
    return 0;
}

edit:

Был смог найти это about -fno-common.

1 Ответ

0 голосов
/ 02 августа 2020

Это распространенное расширение компилятора, популярное в мире Unix. Чтобы отключить расширение, используйте -fno-common.

-fno-common не включен в G CC до версии 10 по умолчанию с любым предупреждением или стандартным параметром. Технически это не является нарушением стандарта, потому что в стандарте это указано как неопределенное поведение. Неопределенное поведение обычно не требует диагностических сообщений c. Реализация может определять поведение, которое стандарт оставляет неопределенным.

Однако это нежелательно, и G CC 10, наконец, по умолчанию -fno-common.

...