这两种易变的限定词用法都是多余的吗?

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(请参阅修订版236142gcc7发行说明)。我想知道是否可以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的答案是否定的,我如何声明volatileC99 6.7.3.8中描述的数组类型?它是https://en.cppreference.com/w/c/language/array中描述的语法(引号后面)吗?

限定词-const,restrict或volatile限定词的任何组合,仅在函数参数列表中允许;这限定了将数组参数转换为的指针类型

让我们考虑一下有关C99的问题。如果C11在这方面有任何差异,请进行记录。

Ant*_*ala 5

TL; DR:

  • 在(1)中,第一和第二个volatile限定词是否都引用int,因此在gcc术语中是“重复的”?(我在这里查看的是C99 6.7.3.4。)

是的,他们双双出线的int,他们是重复。

  • 在(2)中,是否有一个volatile限定符引用了数组的类型以及notint或指针本身,因此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 10volatile -qualified pointers tovolatile 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 intint volatile严格允许的,C标准更喜欢前者。C11 n1570 6.7.6.1p3

  1. 示例下面的一对声明演示了“指向常量值的变量指针”和“指向变量值的常量指针”之间的区别。

    const int *ptr_to_constant;
    int *const constant_ptr;
    
    Run Code Online (Sandbox Code Playgroud)

    指向的任何对象的内容都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说明符与前一种样式一起使用。