为什么标准会产生这种差异?
似乎两者都以相同的方式指定原子类型。
答案 0 :(得分:7)
原子类型说明符: - :)
Syntax: _Atomic ( type-name );
你可以像这样声明一个原子整数:
_Atomic(int) counter;
_Atomic
关键字可以_Atomic(T)
形式使用,其中T是一个类型,作为等同于_Atomic
T的类型说明符。因此,_Atomic(T) x, y;
声明x和y具有相同的类型,即使T是指针类型。这允许简单的C ++ 0x与仅C ++ _Atomic(T)
宏定义兼容为原子。
如果实现不支持原子类型,则不应使用原子类型说明符。 原子类型说明符中的类型名称不应引用数组类型,函数类型,原子类型或限定类型。
与原子类型相关联的属性仅对作为左值的表达式有意义。
If the _Atomic keyword is immediately followed by a left parenthesis, it is interpreted as a type specifier (with a type name), not as a type qualifier.
原子类型限定符: - :)
_Atomic volatile int *p;
It specifies that p has the type ‘‘pointer to volatile atomic int’’, a pointer to a volatile-qualified atomic type.
引用类型为对象类型的指针类型以外的类型不应受限制。
_Atomic
限定符修改的类型不应是数组类型或函数类型。
与限定类型关联的属性仅对于左值的表达式有意义。
如果同一个限定符在同一个specifier-qualifier-list中出现多次,或者直接或通过一个或多个typedef出现,那么行为就像它只出现一次一样。如果其他限定符与说明符限定符列表中的_Atomic
限定符一起出现,则结果类型是如此限定的原子类型。
单独使用关键字_Atomic
作为类型限定符。只要进行适当的转换(包括通过强制转换操作符),允许实现放宽对相应非原子类型具有相同表示和对齐的要求。
答案 1 :(得分:5)
是。它们是有区别的。当它用作类型说明符时,标准将其限制为(6.7.2.4 p(3)):
原子类型说明符中的类型名称不应引用数组类型,函数类型, 原子类型或合格类型。
例如
typedef int arr[5];
当arr
用作限定符时, _Atomic
可以是类型名称,但如果_Atomic
用作类型说明符,则不能用作类型名称(如{{1} }})
答案 2 :(得分:0)
经过多次尝试,我发现了为什么需要这样做:指针!
假设您有:
int foo = 1;
int bar = 2;
int *p = &foo;
图片作为存储位置,前两个保存一个int,最后一个保存指向第一个int的指针。 _Atomic使得这些内存位置适合原子操作。
出于与您的程序有关的原因,您可能需要:
在第一种情况下,要使foo成为原子原子是容易的,在阅读时没有歧义:
_Atomic int foo;
atomic_store_explicit(&foo , 2, memory_order_release); /* valid atomic op. */
但是现在,如果要编写:p,则希望使p原子化。
_Atomic int *p;
...那不是你想要的!
也就是说,如上所述,它是指向原子int的非原子指针。严格来说,不能保证此指针将正确对齐以能够对其执行原子操作(尽管您将很难迫使编译器将指针未对齐!)。这意味着,如果您设法使指针未对齐,则对其执行的原子操作将有机会失败。另一方面,您想要的是一个指向int的原子指针,它不是必需的原子。
所以你必须写:
int bar = 2;
_Atomic (int *) p;
atomic_store(&p , &bar); /* now valid atomic operation */
现在您有了原子指针!
请注意,对于使foo int原子化的非常简单的情况,您也可以编写这三个声明中的任何一个,最后一个使用stdatomic.h中定义的便捷typedef:
typedef _Atomic int atomic_int;
_Atomic int foo;
_Atomic (int) foo;
atomic_int foo;
我通过一个int以及指向和int的指针使它变得“易于理解” ,但是当您不得不处理时
_Atomic (struct foobar *) *q;
您现在将知道q本身不是原子指针,但它指向指向foobar结构的原子指针!
因此,演示:
#include <stdatomic.h>
void test()
{
_Atomic int foo = 1; /* Atomic */
_Atomic int *pf = &foo; /* Non Atomic */
_Atomic int **ppf = &pf; /* Non Atomic */
int bar = 2; /* Non Atomic */
_Atomic (int *) pb = &bar; /* Atomic */
_Atomic (int *) *ppb = &pb; /* Non Atomic */
int *res;
res = atomic_load(ppf); /* Not OK, yields a warning */
res = atomic_load(ppb); /* This is correct */
}
在“测试”功能中:
test.c:13:6:警告:来自不兼容指针类型[-Wincompatible-pointer-types]的分配
res = atomic_load(ppf);
实际上,第一个atomic_load尝试返回一个非原子指针指向一个int:指向的int是原子的,而不是指针。它也可能会失败,因为不能保证&pf(ppf的内容)对于原子操作是正确对齐的(尽管实际上是这样,您必须将pf转换为未对齐的int才能使其失败)。>
第二个atomic_load可以正确使用原子指针,并将其返回到'res'。