Keil C51: возможная ошибка функций с одинаковым именем, но разными параметрами?
Это не совсем вопрос, так как он уже решен. Но я хотел бы поделиться этим здесь, так как кто-то может столкнуться с той же проблемой. И я хотел бы получить более глубокое объяснение по этому поводу.
Я использую Keil µvision3 для программирования на C8051F340(который, я думаю, не имеет отношения к этому вопросу). В моем main.c у меня есть что-то вроде:
... // accessible code
getInput();
... // not accessible after modification
и в mobile.c(игнорировать заголовки, включает в себя, blablabla, которые не имеют значения):
void getInput()
{
...
}
И это было хорошо. Однако после того, как я сделал некоторые изменения в коде,
void getInput(struct SomeStruct *ss)
{
...
}
компиляция и загрузка на чип завершена без ошибок. Хотя я нашел предупреждение:
*** ПРЕДУПРЕЖДЕНИЕ L2: ССЫЛКА, СДЕЛАННАЯ ДЛЯ Неразрешенного ВНЕШНЕГО
СИМВОЛ: ПОЛУЧЕНИЕ
Но я был немного ленив, и у моих коллег было много других предупреждений, которые делали невозможным чтение.(Дурная привычка!)
Что-то, что я хотел бы изучить:
- Почему Keil разрешает такую вещь компилировать без ошибок (в C это определенно должна быть функция, не объявляющая ошибку)?
- Что говорит ССЫЛКА НА РАЗРЕШЕННОЕ ВНЕШНЕЕ? Он нашел функцию с тем же именем, но не смог ее разрешить из-за разных параметров или просто разрешил любую функцию, не проверяя ее существование в проекте? Я не мог найти, как сгенерировать ассемблерный код, поэтому я не совсем уверен.
1 ответ
В C, если вы используете функцию, которая не объявлена в заголовочном файле, компилятор угадывает определение (и зависит от флагов компилятора) и выдает предупреждение. Когда компилятор генерирует код ассемблера, он больше не знает об аргументах, только о символах / символьных указателях, следовательно, компоновщик не может обнаружить это (C++ может, поскольку имена символов там включают информацию о параметрах из-за поддержки перегрузки параметров). pseduecode:
push arg1
call getInput //the linker only sees this, does not know about stack-frame / arguments
Когда дело доходит до предупреждения GETINPUT, кажется, что вы не включаете скомпилированный файл C, содержащий фактический символ, в конечный результат (компоновщик Keil, кажется, помещает символы в верхний регистр, даже если имя должно было быть getInput, или, возможно, вы пытались называть GETINPUT так же?)