gpt4 book ai didi

c - 为什么 __thread 必须跟在 extern 或 static 之后

转载 作者:太空宇宙 更新时间:2023-11-04 01:45:29 25 4
gpt4 key购买 nike

我正在阅读 Kerrisk's book并看到以下作为 31-4 的注释,

  • The __thread keyword must immediately follow the static or extern keyword, if either of these is specified in the variable’s declaration.
  • The declaration of a thread-local variable can include an initializer, in the same manner as a normal global or static variable declaration.
  • The C address (&) operator can be used to obtain the address of a thread-local variable.

我想知道关键字必须在staticextern后面的原因。没有它们就不能使用吗?

它的示例代码,

/*************************************************************************\
* Copyright (C) Michael Kerrisk, 2018. *
* *
* This program is free software. You may use, modify, and redistribute it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation, either version 3 or (at your option) any *
* later version. This program is distributed without any warranty. See *
* the file COPYING.gpl-v3 for details. *
\*************************************************************************/

/* strerror_tls.c

An implementation of strerror() that is made thread-safe through
the use of thread-local storage.

See also strerror_tsd.c.

Thread-local storage requires: Linux 2.6 or later, NPTL, and
gcc 3.3 or later.
*/
#define _GNU_SOURCE /* Get '_sys_nerr' and '_sys_errlist'
declarations from <stdio.h> */
#include <stdio.h>
#include <string.h> /* Get declaration of strerror() */
#include <pthread.h>
#include "tlpi_hdr.h"


#define MAX_ERROR_LEN 256 /* Maximum length of string in per-thread
buffer returned by strerror() */
/* ||||||||||||||||||
// vvvvvvvvvvvvvvvvvv
*/
static __thread char buf[MAX_ERROR_LEN];
/* Thread-local return buffer */


char *
strerror(int err)
{
if (err < 0 || err >= sys_nerr || sys_errlist[err] == NULL) {
snprintf(buf, MAX_ERROR_LEN, "Unknown error %d", err);
} else {
strncpy(buf, sys_errlist[err], MAX_ERROR_LEN - 1);
buf[MAX_ERROR_LEN - 1] = '\0'; /* Ensure null termination */
}

return buf;
}

static void *
threadFunc(void *arg)
{
char *str;

printf("Other thread about to call strerror()\n");
str = strerror(EPERM);
printf("Other thread: str (%p) = %s\n", str, str);

return NULL;
}

int
main(int argc, char *argv[])
{
pthread_t t;
int s;
char *str;

str = strerror(EINVAL);
printf("Main thread has called strerror()\n");

s = pthread_create(&t, NULL, threadFunc, NULL);
if (s != 0)
errExitEN(s, "pthread_create");

s = pthread_join(t, NULL);
if (s != 0)
errExitEN(s, "pthread_join");

/* If strerror() is not thread-safe, then the output of this printf() be
the same as that produced by the analogous printf() in threadFunc() */

printf("Main thread: str (%p) = %s\n", str, str);

exit(EXIT_SUCCESS);
}

最佳答案

线程局部变量的标准 C 存储类说明符是 _Thread_local .该标准还在 §6.11 Future directions 中说:

6.11.5 Storage class specifiers

The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature.

因此,标准规定存储类关键字(staticexternauto — 不要使用它! — register — 同上 — _Thread_localtypedef) 应该出现在声明的开头。出现staticextern_Thread_local的地方,书上推荐的是staticextern 应该是第一个,_Thread_local 第二个。

当然,本书使用的是__thread,而不是_Thread_local。这是一个特定于编译器(实现)的关键字,其行为类似于标准 C _Thread_local 和 Microsoft 的 __declspec(thread)

关于 thread local storage 的 GCC 文档文档(强调已添加):

At the user level, the extension is visible with a new storage class keyword: __thread. For example:

__thread int i;
extern __thread struct state s;
static __thread char *p;

The __thread specifier may be used alone, with the extern or static specifiers, but with no other storage class specifier. When used with extern or static, __thread must appear immediately after the other storage class specifier.

The __thread specifier may be applied to any global, file-scoped static, function-scoped static, or static data member of a class. It may not be applied to block-scoped automatic or non-static data member.

因此,您看到的是 GCC 特定于线程本地存储的表示法,正如我所指出的和 GCC 手册所指出的那样,存储类信息应该在声明中排在第一位(并且 GCC 明确指出 __threadstaticextern 之后。

另见 Common variable attributes .

关于c - 为什么 __thread 必须跟在 extern 或 static 之后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54596755/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com