这些挥发性限定符用法都是多余的吗?

问题描述 投票:5回答:2

考虑

volatile int volatile * volatile vip; // (1)

volatile int volatile * volatile vipa[10]; // (2)

这两行代码都会触发-Wduplicate-decl-specifier(请参阅rev 236142gcc7 release notes)。我想知道我是否可以从给定的代码中删除一些volatile说明符而不改变代码的语义,并理解它背后的原因。

因此,以下问题:

一个。在(1)中,第1和第2个volatile限定符都是指int,因此在gcc术语中是“重复”吗? (我在这里看C99 6.7.3.4。)

湾在(2)中,其中一个volatile限定符是指数组的类型,而不是int或指针本身,因此C99 6.7.3.8包含:

如果数组类型的规范包含任何类型限定符,则元素类型是限定的,而不是数组类型。

或者(2)中的volatile说明符只影响intpointer类型,而不影响数组的类型?

C。如果b的答案是否定的,我如何声明C99 6.7.3.8中描述的volatile数组类型?是https://en.cppreference.com/w/c/language/array描述的语法(引用如下)?

限定符 - const,restrict或volatile限定符的任意组合,仅在函数参数列表中允许;这限定了此数组参数转换到的指针类型

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

c syntax language-lawyer declaration volatile
2个回答
5
投票

TL; DR:

  • 在(1)中,第1和第2个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

如果同一个限定符在同一个specifier-qualifier-list中出现多次,或者直接或通过一个或多个typedef,则行为与它只出现一次相同。

即什么-Wduplicate-decl-specifier不是这样的错误,但这样的代码逐字是可疑的 - 如果volatile int *volatile错误拼写volatile int volatile *导致指针不合格...


限定符适用于限定符左侧的类型,除非限定符本身是最左边的类型,在这种情况下它就好像它是基类型的右边,即

volatile int *

int volatile *

意思是一样的。因此在volatile int volatile你可以删除其中一个。因此,你需要的是

volatile int *volatile vipa[10];

意思是vipais an array of 10volatile-qualified pointers tovolatileint`s。


C99 6.7.3p8 / C11 6.7.3p9的含义是数组本身不能是易失性的 - 它的地址是常量,只有它的元素才能被限定。因此,如果数组类型是合格的,它只适用于其元素。如果typedef合格,情况就是如此:

typedef int intarray[5];
const intarray myarray;

将宣布myarray仿佛

const int myarray[5];

而如果你使用typedef作为指针:

typedef int *intptr;
const intptr myptr;

这个限定符不会影响指向类型,但相当于

int *const myptr;

虽然volatile intint volatile都是严格允许的,但C标准更喜欢前者。 C11 n1570 6.7.6.1p3

  1. 示例下面的一对声明演示了''指向常量值的变量指针''和''指向变量值的常量指针''之间的区别。 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])

这意味着几乎相同,参数衰减到一个合格的指针

void foo(int *volatile array)

但是你只能使用前一种风格的static说明符。


4
投票

解释很简单。

volatile int * == int volatile *

在这种情况下,顺序无关紧要。

所以volatile int * volatile x; == int volatile * volatile x;

如果你有volatile int volatile *你已经宣布它是不稳定的,那么第二个就不需要了

© www.soinside.com 2019 - 2024. All rights reserved.