C 正确的阅读方法';int*ptr=&;x';
下面的代码很容易解释为C 正确的阅读方法';int*ptr=&;x';,c,pointers,initialization,declaration,C,Pointers,Initialization,Declaration,下面的代码很容易解释为 int x=4; int *ptr; // ptr is a pointer to an int ptr=&x; // the address of x is assigned to the pointer ptr 但是下面的等效代码,可能会被误读为 int *ptr=&x; // the address of x is assigned to *ptr, which is an integer 也就是说,它似乎被解释为将x的地址分配给指向的值
int x=4;
int *ptr; // ptr is a pointer to an int
ptr=&x; // the address of x is assigned to the pointer ptr
但是下面的等效代码,可能会被误读为
int *ptr=&x; // the address of x is assigned to *ptr, which is an integer
也就是说,它似乎被解释为将x的地址分配给指向的值*ptr(int*ptr)=&x
当声明和初始化分开时,正确的解释应该写成类似于
int*(ptr=&x)
,以表明赋值是指向指针而不是指向的位置,但这会产生错误,为什么?阅读和思考int*ptr=&x
的最佳方式是什么?int*
是类型,因此它非常有意义。只是C中的指针表示法需要一些努力才能适应。但是看看这个代码
typedef int* int_ptr;
int x;
int_ptr ptr = &x;
同样的事情。但是,通常建议不要使用typedef指针
混淆源于*
有两个角色。命名类型和取消引用指针都是很困难的。第一个例子是sizeof(int*)
如果同时声明几个指针,看起来会更混乱,但仍然是一样的。通常,建议不要一次声明多个指针。因为如果我们想用两个指针来做上面的事情,它看起来是这样的:
int *pa = &x, *pb = &x;
那跟
int *pa = &x;
int *pb = &x;
这将产生一个完全不同的警告,因为您正在将一个变量的地址分配给类型为int
pb的变量
int *pa = &x, pb = &x;
但是,使用上面的typedef,您可以(但可能不应该)执行以下操作:
但有一种方式可以认为,在任何情况下取消对未初始化指针的引用都毫无意义
阅读和思考int*ptr=&x
的最佳方式是什么
假设取消对未初始化指针的引用是没有意义的。您正在对指针进行初始化,因此应该使用(有效)地址对其进行初始化
好吧,我明白了,还有一件事。如果类型是int*
为什么它几乎总是像指针变量旁边的*
那样写,比如int*ptr
?,那么它会更有意义,即使像int*ptr
那样写也是一样的
因为,如果同时声明几个指针,那么忘记星号会容易得多。这给人的印象是int*p,q代码>声明两个指针
C指针语法很笨拙。这是一种非常古老的语言。习惯就好了。它永远不会改变。为了好玩,这里有一个页面可以告诉你什么是声明,所以试试下面这些:
int (*p)[3]
int *p[3]
const int *p[3]
int *const p[3]
const int (*p)[3]
int (*const p)[3]
你可以写
int ( *ptr ) = &x;
甚至像
int ( * ( ptr ) ) = &x;
尽管这张唱片
int *ptr = &x;
对于每个C程序员来说都很清楚,因为它是一个声明而不是赋值语句。此外,在C中,与C++声明相反的不是声明。
也就是说,1)在编写(int*ptr)=&x时,不能将声明括在括号中;2)可以将声明符括在括号中
如果要遵循您的逻辑,那么您应该编写如下声明
int *p = ( p = &x );
这使得声明更加混乱。:)
下面是一个演示程序,它显示了指针声明和初始化的一些示例
#include <stdio.h>
int main(void)
{
int x = 10;
int *p1 = &x;
int ( *p2 ) = &x;
int ( *( p3 ) ) = &x;
int typedef *T;
T ( p4 ) = &x;
printf( "*p1 = %d\n", *p1 );
printf( "*p2 = %d\n", *p2 );
printf( "*p3 = %d\n", *p3 );
printf( "*p4 = %d\n", *p4 );
return 0;
}
请注意,在C语言中,正如在许多其他语言中一样,一些符号是重载的,它们的含义取决于上下文。例如,符号<代码>和<代码>可以表示操作符和位和操作符的地址,并且在C++中,这个符号也可以表示引用。 < P>比较下面的内容。
int n = 5; // (a) defines 'int' variable 'n' and initializes it to '5'
int *p; // (b) defines 'int*' pointer variable 'p`
p = &n; // initializes 'p' to '&n'
int *p1 = p; // (c) defines 'int*' pointer variable 'p1' and initializes it to 'p'
// syntactically, it looks just like (a), but for a pointer type
int *p2 = &n; // (d) same as (b) and (c) combined into a one-liner
int n3 = 7, *p3 = &n3; // (e) same as (a), (b) and (c) combined into a one-liner
诚然,这是C语言中一个奇怪的部分,主要是由于C语言的进化
在C的语法中,声明的目的是镜像使用,因此在int*x
,*x
解析为int
,并且*x=42
分配给该int
。但是,在声明的说明符声明符
部分之后以=
开头的初始化在语法和语义上与赋值不同
(初始化可以“分配”到静态/文件范围变量,这样的分配不会生成代码:它只是对生成的二进制文件的组成起作用。除非优化可以删除它,否则分配始终会生成代码)
在史前的C语言中,初始化和赋值的外观非常不同,在史前C语言中,初始化时不使用=
符号,如intx42代码>。(即使在初始化语法中添加了=
之后,也很难初始化本地、非静态变量,这意味着int*p=&x;
等情况并不经常出现。)
旧语法有问题(会intx(42);
也会声明和初始化x
还是会是函数声明?),这就是为什么它被替换的原因,但我喜欢它强调初始化不同于赋值的方式
不幸的是,对于新语法(如intx,*p=&x;
),这种区别并不明显,您只需记住,当您在左端有类型说明符(int
)时,然后,=
并不表示一个赋值,您可以只查看*p=&x
,而是一个初始化,您必须查看整个声明并查看声明的内容(x
作为int
和p
作为int
的指针)。然后,该上下文中的=
初始化声明的标识符。声明指针时,int p等于int p;int*是一种类型。非常简单,类型是int*
,无论距离int
和*
有多远。你甚至可以写int*ptr=x代码>这仍然是有效的。正确阅读只是习惯问题
*p1 = 10
*p2 = 10
*p3 = 10
*p4 = 10
int n = 5; // (a) defines 'int' variable 'n' and initializes it to '5'
int *p; // (b) defines 'int*' pointer variable 'p`
p = &n; // initializes 'p' to '&n'
int *p1 = p; // (c) defines 'int*' pointer variable 'p1' and initializes it to 'p'
// syntactically, it looks just like (a), but for a pointer type
int *p2 = &n; // (d) same as (b) and (c) combined into a one-liner
int n3 = 7, *p3 = &n3; // (e) same as (a), (b) and (c) combined into a one-liner