我在书中读到的正常指针用法如下:
int *pointer;
int number = 5;
pointer = &number;
则 *指针的值为 5。但这反过来行得通吗?我的意思是:
int *pointer;
int number = 5;
*pointer = &number;
这里的指针包含值 5 和 *pointer 保存数字的地址吗?
谢谢。
in
int *pointer;
int number = 5;
*pointer = &number;
你永远不会给pointer
分配一个有效的地址,所以取消引用该指针(如表达式*pointer
所做的那样(是无效的。
来自牵强类比部门的类比:
您每天都会多次使用指针,甚至不假思索。
指针是一种间接寻址 - 它告诉你某物在哪里,或者如何到达它,但不是那个东西是什么。
(在键入的语言中,您可以知道它是什么样的东西,但那是另一回事。
例如,考虑电话号码。
这些告诉您如何联系电话号码所属的人。
随着时间的推移,那个人可能会改变 - 也许有人没有支付账单并且号码被重新分配 - 但只要号码有效,您就可以使用它来联系一个人。
使用这个类比,我们可以定义以下操作:
-
&person
为您提供一个人的电话号码,并且 -
*number
为您提供该号码所属的人。
一些规则:
- 这种语言只有两种类型——人和电话号码。
- 只有个人可以有电话号码;
&number
是一个错误,*person
也是错误。 - 一个未指明的电话号码到达了Acme,Inc.的客户服务总经理。
现在,您的第一个示例将转换为
PhoneNumber n;
Person Bob;
n = &Bob;
这是有道理的; n
现在持有鲍勃的电话号码。
您的第二个示例将转换为
PhoneNumber n;
Person Bob;
*n = &Bob;
它会说"用鲍勃的电话号码替换Acme Inc客户服务的总经理",这根本没有意义。
你的最后一个问题,
这里的指针包含值 5 和 *pointer 保存数字的地址吗?
将转换为
这个电话号码和鲍勃是一回事吗,如果你拨打它,鲍勃的电话号码会接听吗?
我相信你可以看到这是一个相当奇怪的问题。
第二种情况将无法编译,因为赋值*pointer = &number
涉及不兼容的类型(左侧int
,右侧指向int
的指针(,这使得赋值无效。
如果您以某种方式强制赋值进行编译,则不会初始化pointer
。 访问它的值,更不用说取消引用它(例如,评估*pointer
或像*pointer = number
或*pointer = 5
一样分配给它(会产生未定义的行为。 任何事情都可能发生....根据具体情况,未定义行为的常见结果是程序异常终止。
*pointer = &number;
不是有效的 C。
*pointer
属于 int
类型,&number
属于 int*
类型。这不是有效的赋值形式,不会在标准 C 编译器上编译。
可以将数字存储在指针变量中,但随后必须使用显式强制转换来强制类型转换。一些编译器允许它没有显式强制转换,但请注意,这样做是非标准扩展。
当然,请注意,您尚未将pointer
设置为指向分配的内存地址,因此您无法在它指向的位置存储任何内容。
如果执行显式强制转换,例如
pointer = &something;
*pointer = (int)&number;
那么它在 C 中是允许的,但如果你尝试取消引用该指针,则该行为是实现定义的。在未对齐等情况下,它也可能是未定义的行为。参见C11 6.3.2.3:
整数可以转换为任何指针类型。以前除外 指定,结果是实现定义的,可能不是 正确对齐,可能不指向引用的实体 类型,并且可能是陷阱表示形式。
当你创建一个指针变量时,最初它将具有垃圾值(假设 300 地址位置(。因此,当您取消引用指针(*300(时,它会给出另一个垃圾值(300地址位置的值(或错误(严格来说,根据您的计算机,可能会发生任何事情(。
在第三步中,&number:- 这也是另一个数字,您正在尝试将一个数字分配给 *指针(可能是另一个数字(,这是不可能的。(是这样的:- 5=6(。因此,这将是一个错误。
为了编写赋值x = y
,x
和 y
都必须是或隐式转换为相同的类型(或x
必须有一个用户定义的赋值运算符,采用与y
类型匹配的参数,或者......好的,有几种可能性,但你明白了(。
现在,让我们看一下声明
*pointer = &number;
在这里,*pointer
具有类型 int&
- 您按照指针获取(引用(存储在该位置的整数。现在,让我们忽略这样一个事实,即您的指针未初始化并遵循它会导致未定义的行为。
右侧 &number
是指向整数变量的指针,因此类型为 int*
。
因此,该表达式根本没有意义,仅就类型系统而言:无法将int*
分配给int&
。这没有任何意义。
让我们将其与您问题的英语联系起来
这里的指针包含值 5 和 *pointer 保存数字的地址吗?
这直接转换为类型系统,因此也没有任何意义。同样,我们可以分解它
指针是否包含值 5
指针包含一个位置。唯一有意义的时间是谈论具有文字值的指针(除了
nullptr
(是在有已知地址的平台上 - 这是罕见的,并且"5"不太可能是一个格式良好的地址
无论如何*指针保存地址
好吧,有一种情况
*pointer
可以保存一个地址 - 它是*pointer
本身是一个指针的地方,这意味着变量pointer
是一个指向指针的指针,例如int **
。这里的情况并非如此:我们知道您的代码中的*pointer
类型,它是int&
,而不是int*
。