函数名称和原型中的斜线和点?

时间:2012-11-20 14:58:54

标签: c go notation

我是C的新手,看着Go的源代码树,我发现了这个:

https://code.google.com/p/go/source/browse/src/pkg/runtime/race.c

void runtime∕race·Read(int32 goid, void *addr, void *pc);
void runtime∕race·Write(int32 goid, void *addr, void *pc);

void
runtime·raceinit(void)
{
    // ...
}

斜线和点(·)是什么意思?这是有效的C?

4 个答案:

答案 0 :(得分:19)

  

重要更新:

     go go-nuts邮件列表中的一位Go作者

The ultimate answer is certainly the one you got from Russ Cox。也就是说,我将在下面留下我之前的一些注释,它们可能有助于理解一些事情。

     

此外,通过阅读上面链接的这个答案,我相信“伪斜杠”现在也可以转换为常规/斜杠(就像middot被翻译成点)在较新的版本中Go C编译器比我在下面测试的编译器 - 但我没时间验证。


该文件由Go Language Suite's internal C compiler编译,该文件来自Plan 9 C编译器 (1) (2) has some differences(主要是扩展名) ,AFAIK)符合C标准。

其中一个扩展是,它允许标识符中包含UTF-8字符。

现在,在Go Language Suite的C编译器中,middot字符(·)以特殊方式处理,因为它被转换为目标文件中的常规点(。),由Go Language Suite的内部链接器解释作为命名空间分隔符。

  

实施例

     

对于以下文件example.c(注意:它必须保存为没有BOM的UTF-8):

void ·Bar1() {}
void foo·bar2() {}
void foo∕baz·bar3() {}
     

内部C编译器生成以下符号:

$ go tool 8c example.c
$ go tool nm example.8
 T "".Bar1
 T foo.bar2
 T foo∕baz.bar3
     

现在,请注意我已经·Bar1()为首都B。这是   因为这样,我可以让它对常规Go代码可见 - 因为   它被翻译成完全相同的符号   编译以下Go代码:

package example
func Bar1() {}  // nm will show:  T "".Bar1

现在,关于你在问题中提到的功能,这个故事在兔子洞里走得更远了。如果我就在这里,我不太确定,但我会根据我的知识来解释。因此,低于这一点的每个句子应该被理解为好像它最后写有“AFAIK”。

因此,更好地理解这个难题所需的下一个缺失的部分是了解更多关于奇怪的""命名空间的内容,以及Go套件的链接器如何处理它。 ""命名空间是我们可能想要称为“空”的(因为""对于程序员来说意味着“空字符串”)命名空间,或者更好,是一个“占位符”命名空间。当链接器看到导入如下:

import examp "path/to/package/example"
//...
func main() {
    examp.Bar1()
}

然后它会获取$GOPATH/pkg/.../example.a库文件,并且在导入阶段,每个""使用path/to/package/example替换。所以现在,在链接的程序中,我们将看到如下符号:

 T path/to/package/example.Bar1

答案 1 :(得分:8)

根据我的Javascript控制台,“·”字符为\xB7。 “/”字符为\x2215

该点位于C99 standard列表的附件D 内,哪些特殊字符在C源中作为标识符有效。斜杠似乎没有,所以我怀疑它是通过#define或预处理器魔法用作其他东西(也许是命名空间)。

这可以解释为什么点存在于实际的函数定义中,但斜杠不是。

修改:查看This Answer以获取更多信息。 GCC的实现可能只允许使用unicode斜杠。

答案 2 :(得分:5)

看起来这不是标准C,也不是C99。特别是,即使处于C99模式,gccclang都会抱怨点。

此源代码由Part 9编译器套件(特别是OS X上的./pkg/tool/darwin_amd64/6c)编译,由Go构建系统引导。根据{{​​3}},第8页的底部,Plan 9及其编译器根本不使用ASCII,而是使用Unicode。在第9页的底部,它声明任何具有足够高代码点的字符都被认为在标识符名称中有效。

根本没有预处理魔法 - 函数的定义与函数声明不匹配,因为它们是不同的函数。例如,void runtime∕race·Initialize();是一个外部函数,其定义出现在./src/pkg/runtime/race/race.go;同样适用于void runtime∕race·MapShadow(…)

稍后出现的函数void runtime·raceinit(void)是一个完全不同的函数,它实际上调用了runtime∕race·Initialize();这一事实。

答案 3 :(得分:3)

使用最初为plan9开发的C编译器编译go编译器/运行时。当你从源代码构建时,它将首先构建plan9编译器,然后使用它们构建Go。

plan9编译器支持unicode函数名[1],Go开发人员在其函数名中使用unicode字符作为伪命名空间。

[1]看起来这可能实际上符合标准:g++ unicode variable name但gcc不支持unicode函数/变量名。