尝试class与extern "C"函数结交朋友,此代码有效:
#include <iostream>
extern "C" {
void foo();
}
namespace {
struct bar {
// without :: this refuses to compile
friend void ::foo();
bar() : v(666) {}
private:
int v;
} inst;
}
int main() {
foo();
}
extern "C" {
void foo() {
std::cout << inst.v << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
但是我很惊讶地发现,使用g ++ 4.6.1和4.4.4我必须明确写入::,friend void ::foo();否则友谊不起作用.这::只是在需要的时候才需要extern "C".
extern "C"而不是没有它?名称查找规则的变化如何使其成为必要?我很难过.可能有一些我无法找到的规则.
static关键字将全局变量的范围限制为该转换单元.如果我 static int x在.h文件中使用并且每隔一个文件包含该.h文件,它们是否都属于同一个翻译单元?那么,到处都不会出现x吗?那么静电的作用是什么?
另外,有没有使用static const int x,其中x是一个全局变量?默认情况下,并非所有const全局变量都是静态的 并且const变量的范围仅限于TU,即使它被限制在文件中的for循环中?
我的C++程序需要使用外部C库.因此,我正在使用
extern "C"
{
#include <library_header.h>
}
Run Code Online (Sandbox Code Playgroud)
我需要使用的每个模块的语法.
它一直运作到现在.模块在其头文件中使用此名称作为某些变量.C库本身编译得很好,因为据我所知,这从来就不是C中的关键字.
但是,尽管我使用了extern"C"语法,但当我包含该头文件时,我的C++程序出错了.
如果我每次重命名这与类似的东西C库头文件_this,一切似乎都正常工作.
问题是:
不应在外部的"C"的语法够向后兼容性,至少在语法级别,对于一个头文件?这是编译器的问题吗?
根据"C#语言规范.版本5.0"的"10.12静态构造函数"部分,静态构造函数可以用"extern"修饰符标记,在这种情况下,它被称为外部静态构造函数.
普通(非外部)静态构造器是众所周知的.它们用于初始化静态字段和属性.
外部静态方法通常用于通过P/Invoke调用本机函数.
而且我也知道相当深奥的外部构造函数(另见这个问题).例如,String类有几个这样的声明,这些构造函数由运行时实现.
但是外部静态构造函数的任何实际用法是什么?我搜索了coreclr repo并没有发现任何东西.语言规范无法描述从未在野外使用的某些构造.还是可以吗?
我的猜测:C#有外部静态构造函数,因为CLR支持它们(原则上).
当我只是检查哪些链接被授予外部局部变量时,
我发现编译器之间的一些不同行为
例如,如果我测试了下面的代码,
正如您在评论中看到的那样,变量vars 有不同的链接
// foo.cpp
int var = 10; // external linkage
// main.cpp
#include <iostream>
static int var = 100; // internal linkage
int main() {
extern int var; // internal linkage
std::cout << var << std::endl;
{
extern int var; // g++: external linkage , clang++: internal linkage
std::cout << var << std::endl;
{
extern int var; // g++: external linkage , clang++: internal linkage
std::cout << var << std::endl;
}
}
}
Run Code Online (Sandbox Code Playgroud)
结果是 …
请参阅以下代码:
/* first file */
int i; /* definition */
int main () {
void f_in_other_place (void); /* declaration */
i = 0
return 0;
}
/* end of first file */
/* start of second file */
extern int i; /* declaration */
void f_in_other_place (void){ /* definition */
i++;
}
/* end of second file */
Run Code Online (Sandbox Code Playgroud)
我知道外部对象有external链接,内部对象有none链接(extern暂时忽略)。现在,如果我谈论函数f_in_other_place(),它是在 main 函数中声明的。那么它的标识符会被视为内部对象吗?如果是,则它应该具有none链接,但在程序中可见,此函数指的是它在第二个文件中的定义,该文件显示它的标识符的行为类似于具有external链接的对象。所以我很困惑这里的这个标识符是否有external链接或none链接?
现在谈到extern关键字,我在某处读到了函数声明隐式前缀 …
这是交易.我在两个不同的.c文件中有两个相同的全局变量,它们没有被声明为extern.所以每个.c文件都应该看到自己的变量,对吧?
但是我得到了一些非常奇怪的行为,好像一个文件正在读取其他文件变量(将它们链接在一起之后).将"静态"限定符添加到两个变量定义似乎解决了这个问题.
所以我真正想知道的是,在没有'静态'限定符的情况下究竟发生了什么?
是否可以为constexpr变量分配唯一的地址,即对于变量可用的所有翻译单元(通常通过标题)都是相同的?请考虑以下示例:
// foo.hh
#include <iostream>
constexpr int foo = 42;
// a.cc
#include "foo.hh"
void a(void) { std::cout << "a: " << &foo << std::endl; }
// b.cc
#include "foo.hh"
extern void a(void);
int main(int argc, char** argv) {
a();
std::cout << "b: " << &foo << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
使用gcc 4.7 编译a.cc和b.cc分开并将它们链接在一起,我看到打印了两个不同的地址.如果我extern在标题中添加关键字,我会收到链接器错误duplicate symbol _foo in: a.o and b.o,我觉得有点令人惊讶,因为我认为添加extern更有可能导致编译器从另一个对象导入该符号,而不是从当前对象导出它.但似乎我对这些事情的运作方式的理解是错误的.
是否有合理的方法在一个标题中声明constexpr,这样所有翻译单元都可以在其常量表达式中使用它,并且所有翻译单元都同意该符号的地址?我希望一些额外的代码来表示这个符号实际所属的单个翻译单元,就像没有的extern非extern变量一样constexpr.
我试过以下代码:
FILE1.C:
int x;
Run Code Online (Sandbox Code Playgroud)
file2.c中:
extern char x;
main()
{
x=10;
....
....
}
Run Code Online (Sandbox Code Playgroud)
编译为
$ gcc File1.c File2.c
我没有得到任何错误,但我期待一个.