编译后的 C 程序,调用未定义/未声明的函数;没有报告错误或警告。为什么?

标签 c gcc

我正在复制 Kernighan & Ritchie 的“C 编程语言(第二版)”中的示例。只是为了确保我正确复制了代码(并测试其功能),我编译了以下代码:

/*This is an example program from chapter 5, section 6 (Pointer Arrays; Pointers to Pointers)*/
#include <stdio.h>
#include <string.h>
#include "/home/alecto/Compsci/Cprogramming/Utils/get_line.c"
#include "/home/alecto/Compsci/Cprogramming/Kernighan_Ritchie_5/alloc.c"

#define MAXLINES 5000 /*max number of lines to be sorted*/

char *lineptr[MAXLINES]; /*pointers to lines of text*/

int readlines(char *lineptr[], int nlines);
void writelines(char *lineptr[], int nlines);
void qsort(char *lineptr[], int left, int right);

/* sort input lines */
main()
{
  int nlines; /* number of input lines read */

  if ((nlines = readlines(lineptr, MAXLINES)) >= 0) {
    qsort(lineptr, 0, nlines-1);
    writelines(lineptr, nlines);
    return 0;
  }
  else {
    printf("error: input too big for sort\n");
    return 1;
  }
}
... //readlines() and writelines() are defined in my source file, but not
... //qsort()

尽管源文件中缺少 qsort() 的定义,但程序编译时没有受到 gcc 或链接器的任何提示。我尝试注释掉声明 void qsort(char *lineptr[], int left, int right); 同时保留对 qsort() 的调用在 main 中处于事件状态() 只是为了看看我是否会引发错误,但程序仍然设法安静地编译和运行,没有提示或意外行为

这是怎么回事?

最佳答案

qsort是一个标准库函数,在 <stdlib.h> 中声明.

编译器需要一个可见的声明 qsort ,并且您已在源文件中提供了这样的声明。

链接器需要 qsort定义 ;这是由标准 C 库提供的。该函数与您的声明不兼容,但这不是链接器通常可以检测到的错误。

由于您以与实际函数不兼容的方式声明了标准库函数,因此您的程序具有未定义的行为。

至于为什么当你删除 qsort 声明时你的程序仍然可以编译,那是因为它遵循旧版本的 C 标准。从 C90 标准开始,调用没有可见声明的函数是合法的;编译器假设该函数返回 int 。 C99 放弃了“隐式 int ”规则,要求对此类调用进行编译时诊断 - 但默认情况下 gcc 仍然遵循 C90 标准(具有 gcc 特定的扩展)。使用-std=c99-std=c11要求 gcc 符合更现代版本的 C 标准;添加-pedantic -Wall -Wextra以获得更多警告。

这就是如何让编译器诊断您的错误(尝试重新声明 qsort )。要修复该错误,您需要使用 qsort 以外的名称并且您需要提供有效的声明和定义。

此外,拥有 #include 几乎没有意义。 .c 的指令文件。通常.c文件(提供定义)单独编译,并且 .h文件(提供声明)是 #include d.这是一种约定,而不是语言规则,但遵循它可以使组织代码变得更加容易。关于如何做到这一点还有更多需要了解( header 防护、如何将多个对象链接到单个程序等),但这超出了本问题的范围。

关于编译后的 C 程序,调用未定义/未声明的函数;没有报告错误或警告。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28033335/

相关文章:

c++ - 模板特化适用于 gcc,但不适用于 visual studio 10

assembly - 如何在 GCC 中的函数调用中不使用堆栈?

c++ - 在 C/C++ 文件中定义函数并在 header 中包含相应文件

c - Nicelabel 算法超过 MAX TICKS

php - 如何将自己的内置函数添加到php源代码中?

c++ - 什么时候在 Excel XLL 中释放 FP * 是安全的?

c - Glib/Gio 异步或线程 UDP 服务器

c++ - GCC:为什么编译 .hpp 文件会给出与 .cpp 文件不同的结果?

c++ - 使用 g++、make、cmakelists 在 linux openSUSE 上编译 googletest 程序

c++ - C和C++中的全局变量有什么区别?