我正在阅读Kerrisk's book,并看到以下内容作为31-4的注释,
- 如果
__thread
或static
关键字在变量的 声明。- 线程局部变量的声明可以包含初始化程序,方式与普通的全局变量或静态变量相同 声明。
- C地址(&)运算符可用于获取线程局部变量的地址。
我想知道关键字必须位于extern
或static
之后的原因。没有它们就不能使用吗?
它的示例代码,
extern
答案 0 :(得分:2)
线程局部变量的标准C存储类说明符为_Thread_local
。该标准还在§6.11 Future directions中说:
6.11.5存储类说明符
存储类说明符的放置位置,而不是在声明的开头 声明中的说明符是过时的功能。
因此,该标准说存储类关键字(static
,extern
,auto
—不要使用它!— register
—同上— {{1} }和_Thread_local
)应该出现在声明的开头。在出现typedef
或static
并出现extern
的地方,书中的建议是_Thread_local
或static
应该在第一位,extern
在第二位。
当然,这本书使用的是_Thread_local
,而不是__thread
。这是特定于编译器(实现)的关键字,其行为与标准C _Thread_local
和Microsoft的_Thread_local
类似。
thread local storage个文档上的GCC文档(添加了重点):
在用户级别,可以使用新的存储类关键字
__declspec(thread)
看到扩展名。例如:__thread
__thread int i; extern __thread struct state s; static __thread char *p;
说明符可以与__thread
或extern
说明符一起单独使用,但不能与其他存储类说明符一起使用。与static
或extern
一起使用时,static
必须立即出现在另一个存储类说明符之后。
__thread
说明符可以应用于类的任何全局,文件作用域的静态,函数作用域的静态或静态数据成员。它可能不适用于块范围内的自动或非静态数据成员。
因此,您所看到的是特定于GCC的线程本地存储的表示法,正如我所指出的和GCC手册所指出的,存储类信息应首先出现在声明中(而GCC明确表示{{1 }}在__thread
或__thread
之后。
答案 1 :(得分:1)
重新阅读您引用的文字(强调我的意思):
- __ thread关键字必须紧跟在static或extern关键字之后,如果在变量的声明中指定了两者之一,则必须紧随其后。
因此,如果两者均未指定,则此子句不适用。
至于“为什么”,如果主张是正确的(我怀疑它是正确的,但陈述不准确),这只是“ {@ 1}}来自的“ GNU C”的语法问题。您可以在C11标准中查找等效的__thread
的语法要求。