iks*_*nov 5 c syntax declaration volatile language-lawyer
考虑
volatile int volatile * volatile vip; // (1)
Run Code Online (Sandbox Code Playgroud)
和
volatile int volatile * volatile vipa[10]; // (2)
Run Code Online (Sandbox Code Playgroud)
这两行代码都触发-Wduplicate-decl-specifier
(请参阅修订版236142
和gcc7发行说明)。我想知道是否可以volatile
在不更改代码语义的情况下从给定代码中删除一些说明符,并且也了解其背后的原因。
因此,存在以下问题:
一个。在(1)中,第一和第二个volatile
限定词是否都引用int
,因此在gcc术语中是“重复的”?(我在这里查看的是C99 6.7.3.4。)
b。在(2)中,volatile
限定词之一是引用数组的类型,而不是int
或指针本身,因此C99 6.7.3.8成立:
如果数组类型的规范包括任何类型限定符,则元素类型是合格的,而不是数组类型。
还是volatile
(2)中的说明符仅影响int
和和pointer
类型,而不影响数组的类型?
c。如果b的答案是否定的,我如何声明volatile
C99 6.7.3.8中描述的数组类型?它是https://en.cppreference.com/w/c/language/array中描述的语法(引号后面)吗?
限定词-const,restrict或volatile限定词的任何组合,仅在函数参数列表中允许;这限定了将数组参数转换为的指针类型
让我们考虑一下有关C99的问题。如果C11在这方面有任何差异,请进行记录。
TL; DR:
- 在(1)中,第一和第二个
volatile
限定词是否都引用int
,因此在gcc术语中是“重复的”?(我在这里查看的是C99 6.7.3.4。)
是的,他们双双出线的int
,他们是在重复。
- 在(2)中,是否有一个volatile限定符引用了数组的类型以及
not
int或指针本身,因此C99 6.7.3.8保持:
C99 6.7.3.8 在这里不成立。限定符已经适用于元素类型。可以将限定符应用于具有typedef的数组,但也可以限定元素类型(请参见下文)
C。如果b的答案是否定的,我如何声明C99 6.7.3.8中描述的易失性数组类型?
以一个typedef
为例。
C标准明确允许限定符出现多次。C11 n1570 6.7.3p5:
如果同一限定符直接或通过一个或多个typedef在同一specifier-qualifier-list中多次出现,则其行为与仅出现一次相同。
即-Wduplicate-decl-specifier
不是什么错误,但是这种逐字代码是可疑的-如果是volatile int *volatile
因为错误地volatile int volatile *
导致了指针不合格...
限定符适用于类型左侧左限定符的,除非限定符本身是最左边的一个,在这种情况下,它是因为如果它是基类型即右
volatile int *
Run Code Online (Sandbox Code Playgroud)
和
int volatile *
Run Code Online (Sandbox Code Playgroud)
意思是一样的。因此,volatile int volatile
您可以删除其中之一。因此,您需要的是
volatile int *volatile vipa[10];
Run Code Online (Sandbox Code Playgroud)
意思是vipa is an array of 10
volatile -qualified pointers to
volatile int`s。
C99 6.7.3p8 / C11 6.7.3p9的意思是数组本身不能是易失性的-其地址是恒定的,只有其元素可以被限定。因此,如果数组类型是合格的,则仅适用于其元素。即使typedef是合格的,也是如此:
typedef int intarray[5];
const intarray myarray;
Run Code Online (Sandbox Code Playgroud)
将声明myarray
好像
const int myarray[5];
Run Code Online (Sandbox Code Playgroud)
而如果您将typedef用作指针:
typedef int *intptr;
const intptr myptr;
Run Code Online (Sandbox Code Playgroud)
此限定符不会影响指向类型,但等同于
int *const myptr;
Run Code Online (Sandbox Code Playgroud)
虽然两者volatile int
并int volatile
严格允许的,C标准更喜欢前者。C11 n1570 6.7.6.1p3:
示例下面的一对声明演示了“指向常量值的变量指针”和“指向变量值的常量指针”之间的区别。
Run Code Online (Sandbox Code Playgroud)const int *ptr_to_constant; int *const constant_ptr;
指向的任何对象的内容都
ptr_to_constant
不得通过该指针进行修改,但ptr_to_constant
可以更改为指向另一个对象。类似地,int
指向的内容constant_ptr
可能会被修改,但constant_ptr
其自身始终应指向相同的位置。
还可以在方括号内(但仅在函数参数中)为数组添加类型限定符,因此您可以编写
void foo(int array[volatile])
Run Code Online (Sandbox Code Playgroud)
这意味着几乎相同,并且参数衰减为合格的指针
void foo(int *volatile array)
Run Code Online (Sandbox Code Playgroud)
但您只能将static
说明符与前一种样式一起使用。