【问题标题】:Beginners question - Why does C use * to declare a pointer and not &?初学者问题 - 为什么 C 使用 * 来声明指针而不是 &?
【发布时间】:2020-05-17 23:55:54
【问题描述】:

那么让我们说:

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

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

【问题讨论】:

  • “*”用于表示指针类型,因为这是语法。没有其他理由需要存在。一元 * 运算符(与类型声明不同,无论使用相同的符号)是指针解引用,而 & 一元运算符是地址。
  • “为什么”是什么意思?因为语言语法是这样的,这就是原因。

标签: c cs50


【解决方案1】:

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

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

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

【讨论】:

  • 您所显示的p 的声明(int *p)表示p is a pointer-to-int,我将其读作“int 指针p”,而int *p 中的* 表示'指针',至少对我来说。 YMMV。
  • @BobJarvis-ReinstateMonica:有趣的评论。我通常不大声朗读代码,我可能会阅读 int star p,或者在教法国程序员时阅读 int étoile p。你的发声更明智,更少混乱。 char *argv[] 怎么发音?
  • 我将其发音为“char(发音为 'care' - 我的代码不会闷烧 :-) 指针数组 argv”,或者可能是“char 指针数组 argv”。
【解决方案2】:

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

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

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

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

int *p;

这表明变量p 具有“指向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;
}

引用破坏了这个系统 - 没有&amp;ref 表达式 类型为int,它只是注意到ref 解析为与其他标识符相同的对象。


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

            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

这很重要 - 没有“指向”类型说明符的“指针”。指针性由声明器指定。如果你写类似

int* a, b;

它会被解析为

int (*a), b;

只有a 会被声明为指针。

【讨论】:

    【解决方案3】:

    在 C 中,* 中的变量定义意味着“指向”。在表达式中,&amp; 运算符表示“地址”,而* 运算符表示“取消引用”。

    实际上:

    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&amp; p那样使用&amp;?主要是因为语法不是这样设置的。

    值得注意的是,在 C++ 中,&amp; 重新表示“引用”:

    int n = 1;
    int& r = n;
    

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

    【讨论】:

    • 谢谢!所以这是语法和约定的问题?我正在学习,所以我想确保...
    • creators of C 是这样定义 C 的。
    猜你喜欢
    • 2014-02-17
    • 1970-01-01
    • 2023-02-04
    • 2011-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-03
    相关资源
    最近更新 更多