Предупреждение о неявно определенной функции, работает в 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 необязательно, но настоятельно рекомендуется.

Другие вопросы по тегам