作者littleshan (我要加入剑道社!)
看板C_and_CPP
标题Re: [问题] extern "C"的问题
时间Wed Jun 10 14:59:33 2009
※ 引述《QQ29 (我爱阿蓉)》之铭言:
: 标题: Re: [问题] extern "C"的问题
: 时间: Wed Jun 10 13:46:23 2009
:
: 不好意思 我现在自己想问题测试 其实我对extern "C"真的不是很懂
: z大说的我明白
: 而我现在写法是这样如下
:
: main.cpp
: #include <iostream>
: using namespace std;
: #include "test.h"
先挑一个和标题无关的错误:using namespace 不应该写在任何 #include 之前
这算是满糟糕的写法,因为 compiler 不会报错,
只有在发生名称冲突时才吐一堆不知所云的讯息,而你不会想到是这行写错地方
: 以上这样写 是为了让 test.c不去include test.h(我那个struct .c必须用到)
: 这样可以compile过 但是我继续想办法try
: 我将extern "C"拿掉 test.c改成test.cpp
: 竟然就认不到了...........
你的「认不到」是指 compiler error 还是 link error?
错误讯息是什麽?
main.cpp:
#include "test.h"
int main()
{
foo();
return 0;
}
test.h:
#ifndef TEST_H
#define TEST_H
struct FU;
FU* foo();
#endif // TEST_H
test.cpp
typedef struct FF {
int x, y;
} FU;
FU* foo()
{
return NULL;
}
以上的 code 可以顺利 compile、link 并执行
但其中却隐含了非常邪恶的地方
那就是在 test.h 中并没有 typedef 的叙述
所以你在 test.cpp 中虽然使用了 typedef
但含入 test.h 的 main.cpp 中并不知道「FF」这个 struct 的存在
它得到的资讯仅是:
foo() 是一个函式,不接受参数,传回一个指向 FU 的指标
而 test.cpp 呢?因为 typedef 的缘故,它知道 FU 只是 FF 的别名,
所以你定义的 foo() 是:
foo() 是一个函式,不接受参数,传回一个指向 FF 的指标
所以你的定义和宣告已经如同政客般言行不一了
但运气很好 (从另一个角度来看,应该说不好才对) 的是
C++ 的函式回传型别并不会成为 name mangling 的一部份
所以上述的 foo() 虽然本质上是不同的
但它们在编译时会变成相同的 symbol
因此上述的程式可以顺利连结
如果你改成以下的写法,就过不了关了:
test.h:
#ifndef TEST_H
#define TEST_H
struct FU;
void foo(FU*);
#endif // TEST_H
test.cpp
typedef struct FF {
int x, y;
} FU;
void foo(FU*)
{
return;
}
: 原因很想请板上高手解释一下
:
: 因为我知道struct改成class的话 上面的改法 就不会有问题
C++ 中 struct 和 class 几乎完全相同,
唯一的不同在於 struct 预设成员为 public
而 class 预设成员为 private
其它使用方法完全相同
: 1.为什麽struct却不能呢?
因为你用了 typedef
: 2.一开始我这样故意把.c的include .h拿掉是不是一个好的作法?
不是
因为你的 .c 明显是要实作 .h 提供的介面
不去 include 是自找麻烦
: 不然势必extern "C"就要写在main ==>extern "C"{include "test.h"}
一般会这样写:
#ifndef TEST_H
#define TEST_H
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
typedef struct FF {
int x, y;
} FF;
FF* foo(void);
#ifdef __cplusplus
} // end of extern "C"
#endif // __cplusplus
#endif // TEST_H
这样你的 test.h 就能让 C/C++ compiler 同时使用
: → QQ29:你好~typedef我认知是 定义struct并且给一个(以上)别名之类的 06/10 14:04
: → QQ29:我是不清楚 看很多他人写的程式都很爱使用typedef struct 06/10 14:05
: → QQ29:但是实际上的好处以及在我问的问题上 差异在哪里!! 06/10 14:05
C 里面的 struct 名称不能直接当型别使用,需要在前面多加 struct 关键字:
struct Point {
int x, y;
};
void foo()
{
Point p; // error
struct Point p; // OK
}
所以很多人会这样写:
typedef struct Point {
int x, y;
} Point;
void foo()
{
Point p; // OK
}
但是 C++ 已经没有这层限制了:
struct Point {
int x, y;
};
class Line {
Point start, end;
};
void foo()
{
Point p; // OK
Line l; // OK
}
大大您也是 C_and_CPP 的常客了,也该积极了解自己写出每行 code 的真正意义。
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 219.87.151.2
1F:推 QQ29:谢谢你 我会仔细研究一下 我很积极只是自己功力不够@@ 06/10 15:02
2F:→ QQ29:还是感谢你 thx 06/10 15:02
3F:推 ledia:推 littleshan 的详尽解说 06/10 15:09
4F:推 QQ29:以上的 code 可以顺利 compile、link 并执行<<<上面这边我用 06/10 15:22
5F:→ QQ29:VC的话 他link不到耶 所以我说他认不到... 06/10 15:22
6F:推 dreamboat66:请问文中的__cplusplus是要在哪里define呢? 06/10 15:37
7F:推 VictorTom:推l大的解释:) 06/10 15:38
8F:推 Ebergies:__cplusplus compiler 会自己定义 06/10 15:40
9F:推 zlw:原来是不能直接用struct的型别名称,而不是不能struct s1{;}; 06/10 15:56
10F:→ zlw:我以前是看google搜寻到的文件,解释有误,难怪有经验的前辈 06/10 15:57
11F:→ zlw:都说不先看官方manual却反而去google,这是舍本逐末的作法 06/10 15:57
12F:推 QQ29:是因为compiler会最优先定义__cplusplus所以ifdef才会成立嘛 06/10 16:19
13F:→ QQ29:感觉是compile会在每个cpp最前面加上去define __cplusplus? 06/10 16:19