c和cc的混合编译

问题原理

之前一直以为gcc编译的文件就是C型的目标文件,和源文件的后缀名无关. 这次在做一个小实验的时候发现目标文件的形式是由后缀名决定的.

start.h

void start();

start.c

#include <stdio.h>
void start(){
    printf("start\n");
}

test.cc

#include <stdio.h>
#include <string.h>
#include "start.h"
int main(){
    printf("main\n");
    start();
}
➜  personal_use gcc -c start.c test.cc 
➜  personal_use ld start.o test.o -lc
ld: warning: cannot find entry symbol _start; defaulting to 00000000004002c0
test.o: In function `main':
test.cc:(.text+0x11): undefined reference to `start()'
➜  personal_use nm start.o
                 U _GLOBAL_OFFSET_TABLE_
                 U puts
0000000000000000 T start
➜  personal_use nm test.o
                 U _GLOBAL_OFFSET_TABLE_
0000000000000000 T main
                 U puts
                 U _Z5startv

可以看到虽然都是用gcc编译的,但是test.cc 的目标文件明显是cpp形式的(它的start函数的symbol是被修饰的), 而start.c 则是c形式的目标文件.
所以在进行链接的时候,test.cc会报错找不到_Z5startv这个symbol , 因为test.o 里有的symbol 名字叫start .
总结一下,问题的本质事实上是c和cpp对符号的处理不同,cpp会进行符号修饰, 而c不会, 导致源码里同一个函数在变为符号时会不同,引发歧义.

解决方法

  1. 最简单的就是把他们改成都是c文件或都是cpp文件, 当然也可以都用g++进行编译链接(都变为cpp型目标文件或c型目标文件)

  2. 可以把test.cc 的文件修改一下

    #include <stdio.h>
    #include <string.h>
    #ifdef __cplusplus
    extern "C"
    {
    #endif
    #include "start.h"
    #ifdef __cplusplus
    }
    #endif
    int main(){
        printf("main\n");
        start();
    }
    

    这样在test.cc里声明的start函数使用的就是c型的symbol,不会产生歧义.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值