Предупреждение о неявно определенной функции, работает в Clang, не работает в GCC 5.4
У меня есть один участник базового курса Си, который создал тайну. Задача состоит в том, чтобы написать функцию double square_to(double *)
который просто возводит в квадрат число на месте, а также возвращает результат.
Разобранный код выглядит так:
main.c
:
#include "mymath.h"
#include <stdio.h>
int main() {
double t = 5;
double *p;
double m;
p = &t;
m = square_to(p);
printf("%f\n%f\n", t, m);
return 0;
}
mymath.h
:
#ifndef MYMATH_H
#define MYMATH_H
double square_to(double *p);
#endif
mymath.c
:
#include "mymath.h"
#include <stdio.h>
double square_to(double *p) {
*p = (*p) * (*p);
return *p;
}
Флаги компиляции:
-Wall -pedantic -o day5 main.c mymath.c
Я не вижу в этом ничего плохого. Он также отлично работает с Clang и GCC на его Ubuntu и моей Fedora. Программа выводит 25.000
дважды в каждом случае.
Часть, где это становится странным, - когда его оригинальные файлы используются. Есть несколько других функций из других частей курса в mymath.c
, Эти функции компилируются по-видимому. в main.c
его GCC 5.4 предупреждает о неявном объявлении square_to
, При запуске программы она выводит 25.000
и какое-то случайное число, которое представляется целым числом. Повторный запуск выдает другое число. Поэтому это не проблема приведения, это реальное неопределенное поведение.
Компилирование того же кода с помощью Clang (просто обмен gcc
с clang
в командной строке, -Wall
а также -Wpedantic
активно), работает просто отлично, даёт 25.000
в каждом случае. Это красный флаг, так как стандартный совместимый код должен прекрасно компилироваться с обоими компиляторами. На моей установке Fedora это работает с GCC 6.2.1.
Полный код в этой сути.
Я понятия не имею, почему полный код изменяет поведение square_to
функция. Что не так с полной программой?
Обновить
Перед тем, как покинуть учебник, я попросил студента загрузить код в суть и скомпилировать его. Он сделал это с gcc -Wall -pedantic main.c mymath.c
и скомпилировано без ошибок. Запуск это дало 25.000 25.000
так, как это должно быть.
Так что проблема нигде в любом коде, который у меня есть. В каталоге, из которого он работает, должно быть что-то очень странное. Я дважды проверил путь в редакторе и терминале, я также сделал less main.c
и это был правильный.
Сейчас нет возможности ответить на этот вопрос, так как у меня нет ничего, чтобы воспроизвести проблему. У участника также были различные другие подобные проблемы. Смотрите их здесь:
Там видно, что функция как-то вызывается с double *
хотя есть только int
в функциях. затем gcc
указывает на декларацию, которая предположительно конфликтует, и это тот же самый прототип.
Я за закрытие этого вопроса, потому что ничему больше нельзя научиться, не имея доступа к конкретной среде, которую имел участник. Он просто сказал, что завтра начнет работать в новом каталоге. Если это все еще сохраняется, я соберу весь каталог.
1 ответ
From: Неявные объявления функций иногда работают в C?
Если выражение, которое предшествует списку аргументов в скобках в вызове функции, состоит исключительно из идентификатора, и если для этого идентификатора не видно никакого объявления, идентификатор неявно объявляется точно так, как если бы в самом внутреннем блоке, содержащем вызов функции, объявление
extern int identifier();
появился.
Поскольку main.c считает, что функция должна возвращать int
, это то, что вы получите (позже приведете к двойному в назначении).
На процессорах Intel и AMD под управлением Linux целые числа возвращаются в rax
и двойники возвращаются в регистрах с плавающей запятой. Поэтому я предполагаю, что в этом случае целое число, которое вы видите, - это то, что произошло в rax
зарегистрироваться, когда функция вернулась.
Но это только предположение, неопределенное поведение не определено.
Поскольку кажется, что существует некоторая путаница: если вы получаете предупреждение о неявных декларациях, это означает, что GCC не видел никаких действительных деклараций перед использованием. Либо так, либо ваш компилятор сломан.
Правильное объявление функций int-return в C<99 необязательно, но настоятельно рекомендуется.