C中的指针语法:为什么*仅适用于第一个变量?

EMP*_*EMP 22 c syntax pointers language-design

C中的以下声明:

int* a, b;
Run Code Online (Sandbox Code Playgroud)

将声明a为类型int*b类型int.我很清楚这个陷阱,但我想知道的是它为什么会这样运作.为什么它不也宣布b作为int*,因为大多数人会直觉地想到?换句话说,为什么*适用于变量名,而不是类型?

当然你可以用这种方式写它,以便与它的实际工作方式更加一致:

int *a, b;
Run Code Online (Sandbox Code Playgroud)

但是,我和我所说过的每个人都用"指向int"的类型来思考,而不是指向某些数据的指针,而该数据的类型是"int".

这对C的设计者来说只是一个糟糕的决定还是有一些很好的理由为什么它会被这样解析?我确定之前已经回答了这个问题,但我似乎无法通过搜索找到它.

caf*_*caf 31

C语句以这种方式编写,以便"声明镜像使用".这就是你声明这样的数组的原因:

int a[10];
Run Code Online (Sandbox Code Playgroud)

你是否拥有你提出的规则,总是在哪里

type identifier, identifier, identifier, ... ;
Run Code Online (Sandbox Code Playgroud)

...那么数组逻辑上必须像这样声明:

int[10] a;
Run Code Online (Sandbox Code Playgroud)

这很好,但不反映你如何使用 a.请注意,这也适用于函数 - 我们声明这样的函数:

void foo(int a, char *b);
Run Code Online (Sandbox Code Playgroud)

而不是

void(int a, char* b) foo;
Run Code Online (Sandbox Code Playgroud)

一般情况下,"申报镜子使用"的规则意味着你只需要记住一组关联规则,适用于像无论是运营商*,[]()当你使用的价值,像声明符相应的令牌*,[]().


经过一番思考后,我认为值得指出的是,将" 指向int "的拼写为" int*"只是"声明镜子使用"的结果.如果你打算使用另一种声明形式,将" 指向int "的拼写为" &int"或者像" @int" 这样完全不同的东西可能会更有意义.

  • 嗯,这对我来说听起来不是一个很好的理由。我*确实*想将数组声明为`int[10]`,Java 和C# 就是这样做的。声明镜像使用的 C 语法中是否还有其他示例? (2认同)
  • @Evgeny,C 是一种与 Java 截然不同的语言。Java 数组完全不同。数组变量只保存对数组的可修改引用。AC数组变量*是*数组。“声明镜像使用”的另一个例子是函数声明返回一个指向整数的指针。`int *foo(int bar);`。这反映了`*foo(3)` 是一个整数的事实。我建议你阅读 K&R C 2nd ed.,在那里解释了这一点。 (2认同)
  • @Evgeny:最明显的另一个例子是函数声明,它看起来像函数调用。 (2认同)

cap*_*232 17

有一个关于C语言开发的网页说:"这些声明的语法反映了在表达式中使用i,*pi和**ppi都会产生int类型的观察结果." 在页面上搜索该句子以查找关于此问题的相关部分.


eru*_*orm 9

可能还有其他历史原因,但我总是这样理解:

一种声明,一种类型.

如果a,b,c和d必须与此类型相同:

int a, b, c, d;
Run Code Online (Sandbox Code Playgroud)

然后,该行上的所有内容也必须是整数.

int a, *b, **c, ***d;
Run Code Online (Sandbox Code Playgroud)

4个整数:

  1. 一个
  2. *b
  3. **C
  4. ***d

它也可能与运算符优先级有关,或者它可能在过去的某个时刻.

  • @Georg,eruciform是正确的.从K&R C开始,"指针ip的声明,`int*ip`,用作助记符;它表示表达式`*ip`是一个`int`.变量声明的语法模仿语法变量可能出现的表达式.这*是*语法的原因. (3认同)
  • @Georg,他从未说过"这就是我理解语法的方式"他对语言设计的理解*是语言设计的真正原因. (2认同)