初学者问题——为什么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 声明遵循通常被描述为“声明模仿使用”的约定。声明的结构与代码中表达式的结构匹配(尽可能接近)。
例如,假设您有一个指向名为 p
的 int
的指针。要访问存储在指向对象中的值,我们 取消引用 带有一元 *
运算符的指针,如下所示:
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
会被声明为指针。
所以让我们说:
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 声明遵循通常被描述为“声明模仿使用”的约定。声明的结构与代码中表达式的结构匹配(尽可能接近)。
例如,假设您有一个指向名为 p
的 int
的指针。要访问存储在指向对象中的值,我们 取消引用 带有一元 *
运算符的指针,如下所示:
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
会被声明为指针。