如何声明与原定义签名不同的libc函数?解决getchar编译冲突
解决getchar重定义与标准库冲突的问题
问题重现
你在实现自制编译器的外部函数时,编写的runtime.c代码中重定义了getchar函数:
#include <stdio.h> #include <stdlib.h> ... #undef getchar struct string *getchar() {int i=getc(stdin); if (i==EOF) return ∅ else return consts+i; }
使用clang编译时出现类型冲突错误:
$ clang -O3 -S -target mips -mcpu=mips32 -std=c89 runtime.c runtime.c:105:16: error: conflicting types for 'getchar' struct string *getchar() ^ /usr/include/bits/stdio.h:47:1: note: previous definition is here getchar (void) ^ 1 error generated.
你尝试了-fno-builtin和-fno-builtin-getchar选项,但无效果。
解决方案
冲突的核心是<stdio.h>中已经声明了int getchar(void),而你定义的struct string *getchar()类型不匹配。-fno-builtin系列选项仅控制编译器是否将getchar视为内置优化函数,无法屏蔽头文件中的函数声明,因此需要通过预编译手段在包含头文件时屏蔽标准库的getchar声明:
方法1:预编译宏替换屏蔽标准库声明
在包含<stdio.h>之前,用宏将getchar替换为临时名称,避免头文件中留下该函数的声明:
// 先定义宏替换getchar,避免stdio.h中声明该函数 #define getchar __std_getchar #include <stdio.h> #undef getchar #include <stdlib.h> ... struct string *getchar() { int i = getc(stdin); if (i == EOF) return ∅ else return consts + i; }
这样<stdio.h>中的getchar会被替换为__std_getchar,编译器不会识别到标准库的getchar声明,你的重定义就不会产生冲突。
方法2:编译时添加-Ugetchar选项
clang的-U选项用于取消预定义的宏,你可以在编译命令中添加该选项,尝试屏蔽标准库中通过宏定义的getchar:
clang -Ugetchar -O3 -S -target mips -mcpu=mips32 -std=c89 runtime.c
如果标准库的getchar是通过宏实现的,这个方法可以直接生效;若为函数声明,则优先使用方法1。
补充说明
Andrew Appel的《Modern Compiler Implementation in ML》中的代码针对的是较旧的编译器环境(如早期GCC),这类编译器对函数声明的检查不如现代clang严格,因此需要调整代码适配现代编译器的规则。
内容的提问来源于stack exchange,提问作者ksrk
相关产品推荐
相关产品推荐

