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

Are both of these volatile qualifier usages redundant?

考虑

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

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

两行代码触发-Wduplicate-decl-specifier(参见rev 236142gcc7 release notes)。我想知道我是否可以在不改变代码语义的情况下从给定代码中删除一些 volatile 说明符,并了解其背后的原因。

因此,以下问题:

a。在 (1) 中,第一个和第二个 volatile 限定符是否都引用 int,因此在 gcc 术语中是 "duplicate"? (我在这里查看 C99 6.7.3.4。)

b。在 (2) 中,volatile 限定符之一是否引用数组的类型,而不是 int 或指针本身,因此 C99 6.7.3.8 持有:

If the specification of an array type includes any type qualifiers, the element type is so-qualified, not the array type.

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

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

qualifiers - any combination of const, restrict, or volatile qualifiers, only allowed in function parameter lists; this qualifies the pointer type to which this array parameter is transformed

让我们考虑这是一个关于 C99 的问题。如果C11在这方面有什么不同,请指出。

长话短说:

  • In (1), do the 1st and 2nd volatile qualifiers both refer to int, thus being "duplicate" in gcc terms? (I'm looking at C99 6.7.3.4 here.)

是的,它们都符合 int 并且它们是 重复项。

  • In (2), does one of the volatile qualifiers refer to the type of the array, and not the int or the pointer itself, so that C99 6.7.3.8 holds:

C99 6.7.3.8 在这里。限定符已经应用于元素类型。可以将限定符应用于具有 typedef 的数组,但这也限定了元素类型(见下文)

c. If the answer to b is negative, how do I declare a volatile array type that is described in C99 6.7.3.8?

typedef为例。


C 标准明确允许限定符出现多次。 C11 n1570 6.7.3p5:

If the same qualifier appears more than once in the same specifier-qualifier-list, either directly or via one or more typedefs, the behavior is the same as if it appeared only once.

-Wduplicate-decl-specifier 本身不是错误,但这样的代码逐字 可疑的 - 应该是 volatile int *volatile 被拼错为 volatile int volatile * 导致指针不合格...


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

volatile int *

int volatile *

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

volatile int *volatile vipa[10];

意思是 vipais an array of 10volatile-qualified pointers tovolatile</code>int`s.</strong> </p> <hr> <p>C99 6.7.3p8/C11 6.7.3p9 的意思是 <em>array</em> 本身不能是易失的——它的地址是常量,只有它的元素可以被限定。因此,如果一个数组类型被限定,它只适用于它的元素。如果 typedef 是合格的,情况也是如此:</p> <pre><code>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. EXAMPLE The following pair of declarations demonstrates the difference between a ''variable pointer to a constant value'' and a ''constant pointer to a variable value''.

    const int *ptr_to_constant;
    int *const constant_ptr;
    

    The contents of any object pointed to by ptr_to_constant shall not be modified through that pointer, but ptr_to_constant itself may be changed to point to another object. Similarly, the contents of the int pointed to by constant_ptr may be modified, but constant_ptr itself shall always point to the same location.


还可以在括号内为数组添加类型限定符,但只能在函数参数中,因此您可以写

void foo(int array[volatile])

这意味着几乎相同并且参数衰减为合格的指针

void foo(int *volatile array)

但是您只能在前一种样式中使用 static 说明符。

解释很简单。

volatile int * == int volatile *

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

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

如果你有 volatile int volatile * 你已经将它声明为 volatile 不需要第二个