Есть ли опция компилятора gcc, которая помогает фиксировать формальное и фактическое несоответствие типов параметров? - PullRequest
0 голосов
/ 20 мая 2019
//file1.c
#include <stdio.h>
void p(int a)
{
  printf("%d\n",a);
}

//file2.c
 extern void p(float x); // external declaration doesn't match definition
int main(){
  float b;
  b=3.333f;
  p(b);
}

Здесь внешнее объявление неверно в том смысле, что оно отличается от фактического определения функции.Я компилирую и связываю два файла с помощью:

gcc -Wconversion -Wall -std=c99 file1.c file2.c

Предупреждение не вызывается.Есть ли опция компилятора gcc, которая может помочь отловить это несоответствие во время компиляции / компоновки?

Ответы [ 2 ]

4 голосов
/ 20 мая 2019

При компиляции file2.c компилятор не может наблюдать, что объявление в нем не совпадает с объявлением в file1.c, поскольку при компиляции file2.c компилятор не знает содержимого из file1.c.

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

Такое несоответствие обычно обрабатывается с помощью заголовочных файлов. Общепринятая практика - включать объявления из заголовка, а не вводить их вручную в другие исходные файлы. Для этого:

  • Создайте file1.h и поместите в него void p(int a);.
  • В file1.c вставить #include "file1.h".
  • В file2.c вставьте #include "file1.h" и удалите объявление p.

Цель включения file1.h в file1.c состоит в том, чтобы компилятор увидел и объявление в file1.h, и определение в file1.c, и он будет жаловаться, если они несовместимы.

Тогда, поскольку file1.h включен в file2.c, мы уверены, что объявление, замеченное при компиляции file2.c, совместимо с определением в file1.c.

2 голосов
/ 20 мая 2019

Этот код вызывает неопределенное поведение, потому что функция вызывается через объявление, несовместимое с определением функции.

Чтобы помочь с этим, вы можете:

  • использовать -flto который будет выполнять проверки прототипа во время соединения
  • использовать -Wmissing-declarations, который предупредит о том, что file1 имеет функцию с внешней связью, но нет прототипа
  • принимает привычку никогда не писать вручную extern объявление функции в файле .c - всегда включайте файл .h, который также включен в файл .c, содержащий определение функции (предыдущая опция предупредит об этом).
...