关于 extern "C"
当这个世界还只有C的时候,是不需要extern "C"的。
但是,当C++出现之后,有时候,我们就需要extern "C"了。
那究竟是在什么样的情况下,我们需要用extern "C"呢?
有人说,是为了C能够调用C++,有人说是为了在C++中能调用C的库函数。是不是把你弄糊涂了?
先说说extern "C"是啥作用吧。
extern "C" 是告诉C++编译器,这个函数是完全兼容C的,不包含C++有而C中没有的特性的。并且告诉编译器,在生成目标文件的时候,使用C的方式生成函数名。
上面这句话有两个重点,
第一是 extern "C" 只有 C++编译器认得,C编译器是不认识的。
第二是 用C的方式生成函数名。什么叫 "用C的方式生成函数名"? C++编译器和C编译器生成函数名的方式是不同的。因为C++要支持函数重载,所以C++编译器在生成函数名的时候会把函数参数的类型加在函数名中。而C编译器就比较简单,直接在函数名字前加一个下划线搞定。
比如 void foo( int x ); 这样的函数
C编译器编译出来在符号库中的名字是_foo,而C++编译器编译出来在符号库中的名字可能是 _foo_int 这样的。
那么使用 extern "C" 有什么意义呢?
我觉得 ”为了C++中能调用C的库函数“ 这样的说法是正确的。
为什么?
考虑下面的情况,你有一个C实现的库,并用C编译器编译生成库文件。
假设这个库里有一个函数为 void foo( int );
在C++的某个类中,你要用这个foo函数,你在C++源文件中用
extern void foo( int );
引入。
这样在链接的时候出错了。
因为C++编译器在编译C++源文件的时候,认为void foo( int ); 在符号表中应该是
_foo_int 这个样子的。而在链接的时候找不到_foo_int,只有_foo。所以链接出错了。
怎么解决呢?
extern void foo( int );
改成
extern "C" void foo( int );
就行啦。
如果是直接include C的头文件的,那可以这样
extern "C" {
#include "HeaderOfC.h"
}
这样C++编译器就知道,这个foo是C的函数,生成名字的时候不需要带参数。这样链接的时候就没问题啦。
那么在今天,我们写一个C的库的时候,当然存在我们的库被C++的程序所使用的可能性。
我们不希望在C++的源码中引用我们的头文件的时候还要
extern "C" {
#include "yourlib.h"
}
这么麻烦。
所以我们在写C的库的头文件的时候主动的加上了 extern "C"。
但这里有一个问题,因为C编译器不认识extern "C"啊,所以就有了
宏 __cplusplus
对于C编译器,没有定义这个宏,而C++编译器定义了这个
相关文档:
In C++, how do i go about using setenv to set the display? I need to set it like this:
export DISPLAY=0.0
1、setenv("DISPLAY",":0.1",1);
If you're calling the xrandr functions from your C++ program, then I would expect setenv() should work for you. The 3rd argument of 1 tells setenv() to ov ......
问题描述:
C#程序,里面copy了许多原来的代码,所以参差不齐的,很难读,如何才能让代码自动排齐,就象VS 6.0中可以使用快捷键,非常方便.
解答:
ctrl+a,先全选
ctrl+k,ctrl+f,自动排列
或者
ctrl+a,先全选
alt+F8 自动排列 ......
C的static的用法:
1.对于函数里的局部变量,改变的是它的生存周期,这个变量会一直存在,到程序结束. 函数外部访问不到这个变量.
2.对于全局的变量,改变的是它的作用范围,这个变量只在本文件内有效.其它的.c文件看不到.
当然它的生命周期是和程序一样的 ......
快速幂取模理论基础: 计算 a^b mod c ?
由(a x b) mod c=((a mod c) x b) mod c.
我们可以将 b先表示成就:
b=at2^t+at-1 2^t-1+……a02^0. (ai=[0,1]).
这样我们由 a^b mod c=(a^(at2^t+at-12^t-1+…a02^0)mod c.
然而我们求 a^(2^(i+1)) ......