初学者问题——为什么C用*声明指针而不用&?

Beginners question - Why does C use * to declare a pointer and not &?

所以让我们说:

int n = 50;
int *p = &n;

为什么我们在 C 中使用 * 而不是 &*& 之间的主要区别是什么?

在C中*在变量定义中表示"pointer to"。在表达式中,& 运算符表示 "address of",而 * 运算符表示 "dereference".

所以实际上:

int n = 1;
int* p = &n; // Create a pointer and initialize with the address of n

if (*p == 1) {
  // This is true when dereferencing the pointer
}

为什么不像 int& p 那样使用 &?主要是因为语法不是那样设置的。

值得注意的是,在 C++ 中,& 返回表示 "reference":

int n = 1;
int& r = n;

请注意,右侧不需要任何特殊处理,它只是计算出来。

使用*声明指针主要是约定俗成的问题,但有一个一致性的原因:声明int *p中的*表示int*p.

的类型

写成 int &p = &n 似乎更一致,因为 p 被初始化为 n 的地址,但这个约定不适用于双指针: int **pp 定义pp 作为指向 int 的指针的指针,但 pp 不能用 &(&n) 初始化。

请注意,int& p = n; 是 C++ 中对 int 的引用的有效定义,它是伪装的指针。修改 p 会修改 n。引用被实现为没有间接表示法的指针。

C 声明遵循通常被描述为“声明模仿使用”的约定。声明的结构与代码中表达式的结构匹配(尽可能接近)。

例如,假设您有一个指向名为 pint 的指针。要访问存储在指向对象中的值,我们 取消引用 带有一元 * 运算符的指针,如下所示:

printf( "value of what p points to is %d\n", *p );

表达式*p的类型为int,所以我们声明p

int *p;

这表示变量 p 的类型为 "pointer to int",因为 p 组合 和取消引用运算符 * 在声明符中产生类型为 int 的表达式。

这就是为什么在 C 中不使用 & 运算符声明指针的主要原因,因为 表达式 &p 的类型不会是 int

C++ 使用一元运算符 & 来声明 引用 ,这与指针不是一回事:

void foo( int &ref )
{
  ref = new_value(); // writes a new value to the actual parameter ref references
}

int main( void )
{
  int x = 1;
  std::cout << "x before foo = " << x << std::endl;
  foo( x );
  std::cout << "x after foo = " << x << std::endl;
  return 0;
}

引用有点破坏这个系统 - 没有类型为 int&ref expression,它只是指出 ref 解析为与其他标识符相同的对象。


C 声明由两部分组成 - 一系列 声明说明符 (存储 class 说明符、类型限定符、类型说明符)随后是一系列(可能已初始化)声明符。指针性、数组性和函数性在声明符中指定:

            declaration specifiers           declarators
                     |                           |
+--------------------+----------------+ +--------+--------+
|                                     | |                 |
static const volatile unsigned long int a[10], *p, f(void);
   |   |            | |               | |      |   |
   |   |            | |               | |      |   +––––––– function declarator
   |   |            | |               | |      +––––––––––– pointer declarator
   |   |            | |               | +––––––––—–––––——–– array declarator
   |   |            | +–––––––+––––––—+
   |   |            |         |
   |   |            |         +––––––––––––––——–––––––––––— type specifiers
   |   +––––––+–––––+
   |          |
   |          +–––––––––––––––––––––––––––––––––––––––––––– type qualifiers
   +–––––––––––––—––––––––––––––––––––––––––––––––––––––––– storage class specifier

这很重要 - 没有 "pointer to" 类型说明符。指针性由声明符指定。如果你写类似

int* a, b;

它将被解析为

int (*a), b;

并且只有 a 会被声明为指针。