看看下面的两个代码示例!
int main() {
int a = 12;
int *p;
*p = a;
}
而这段代码,
int main() {
int a = 12;
int *p;
p = &a;
}
在第一段代码中,指针被解引用为
*p = a
,而在第二段代码中,变量 a
的地址被设置为指针变量。我的问题是这两段代码之间有什么区别?
看看下面的两个代码示例!
int main() {
int a = 12;
int *p;
*p = a;
}
int main() {
int a = 12;
int *p;
p = &a;
}
*p = a
,而在第二段代码中,变量 a
的地址被设置为指针变量。在您的第一段代码中:
int main() {
int a = 12;
int *p;
*p = a;
}
p
int变量。然而,p
还没有被分配一个“地址”,因此它将具有任意 - 以及无效的值!一些编译器可能会将p
初始化为零(或NULL
),但这仍然是一个无效的地址(在大多数系统上)。int main() {
int a = 12;
int *p;
p = &a;
}
这里,你正在为指针变量 p
分配一个值(即一个地址);在这种情况下,p
现在指向变量 a
(也就是说,它的值是变量 a
的地址)。
因此,如果您将以下代码附加到第二段代码的末尾:
*p = 42;
如果您打印a
的值,您将看到它的值已从最初给定的12
更改为42
。
如需进一步澄清和/或解释,请随时提出。
printf("The address is %p\n", p)
),它会打印一个地址。那里发生了什么? - Azeem Muzammil声明*p
和a
会在内存中保留一些空间,第一种情况是为指针保留空间,在第二种情况下是为a
(一个int
)保留空间。
在这两种情况下,如果您不放入任何内容,则它们的值未被初始化。那并不意味着里面什么也没有,因为这是不可能的。这意味着它们的值是不确定的,有点像“随机”;加载程序在请求时将代码/数据放入内存中,并且由p
占用的空间以及由a
占用的空间都是加载时内存中存在的内容(也可以是编译时,但无论如何都是不确定的)。
因此,在第一种情况下执行*p = a
会有很大的风险,因为您要求处理器将a
“内部”的字节存储在p
指向的任何位置。它可能在数据段的边界内,在堆栈中,在不会引起立即问题/崩溃的某个位置,但可能性很大是不行的!
这就是为什么这个问题被称为“未定义行为”(UB)的原因。
int main() {
int a = 12;
int *p;
*p = a;
}
a
的值放入指针p
所指向的位置。但p
指向什么?可能没有指向任何东西(NULL)或任何随机地址。在最好的情况下,它可能会导致执行错误,例如访问冲突或分段错误。在最坏的情况下,它可能会覆盖完全未知变量的任何现有值,从而导致非常难以调查的问题。
第二个没问题。
int main() {
int a = 12;
int *p;
p = &a;
}
a
的指针,并将其分配给指针p
。因此,这将正常工作。为了解释它们之间的差异,我们必须分别看看这些人:
首先我们需要了解什么是引用。引用是一个对象的标识符,例如我们可以说“变量a
代表着值12
”,因此a
是指向12
值的引用。
对象的标识符是存储在其中的值的引用。
指针也是一样的。指针就像普通的对象一样,它们内部存储一个值,因此它们将这些存储的值作为引用。
“解引用”是当我们“禁用”与通常值之间的连接并使用p
的标识符来访问/引用与p
中存储的值不同的另一个值时发生的。
“解引用指针”意味着您使用指针访问存储在另一个对象中的值,例如在a
中的12
,而不是通过其自身的标识符a
。
要解引用指针,需要在指针变量之前加上*
解引用运算符,如*p
。
通过将指针的值设置为另一个对象的地址,类似于给普通变量赋值的方式,我们实现了“什么是解引用指针?”中所述的内容。
但与通常的对象初始化/分配不同,我们需要使用&符号运算符,在变量之前,其值应该由指针指向,而*解引用运算符则必须省略,如下所示:
p = &a;
首先要做的是声明一个指针,例如:
int *p;
int
的对象的指针变量p
。
第二步是使用类型为int
的对象的地址值初始化指针:
int a = 12;
p = &a; //Here we assign the address of `a` to p, not the value of 12.
&
,在对象之前。
*
运算符来访问指针所指向的对象的值。 *p = a;
int main() {
int a = 12;
int *p;
*p = a;
}
通过解引用指针寻址对象是无效的。如果没有先进行一次引用来确定指针所指向的对象,就不能给指针的解引用赋值。
因此,你的假设:
在第一段代码中,我将指针解引用为 *p = a...
是错误的。
在这种情况下,你不能以正确的方式使用 *p = a
解引用指针,因为指针 p
没有任何引用,你无法正确地对指针进行解引用。
实际上,使用语句 *p = a
将值 a
分配到内存的某个位置。
通常,编译器不应该让这样的代码通过而不报错。
如果发生了这种情况,并且你稍后想要使用指针正确地分配的值,例如 printf("%d",*p)
,你将会得到一个 Segmentation fault (core dumped)
错误。
p
指向哪里(例如,作为其值的p
持有哪个有效地址)?” 在第二个例子中,你将a
的地址赋给了p
—— 现在p
持有a
的地址作为其值(例如,p
指向a
)。请记住,指针只是一个正常的变量,它将其他东西的地址作为其值。 - David C. Rankin