我正在阅读斯坦福大学的Essential C文档(PDF)和第20页,其中列出了以下代码:
int* p
*p = 13; // NO NO NO p does not point to an int yet
// this just overwrites a random area in memory
这对我没有意义。
据我了解,我们为第一行的整数指定空间,所以为什么我们不能在第二行直接指向一个整数的值(例如13)。
请详细解释(图表非常有用)正在发生的事情以及失败的原因。
答案 0 :(得分:12)
int *p;
*p = 13;
这意味着:
p
。 图形:
+---+ +---+
| p | --> points to ?????? | |
+---+ +---+
^
|
13 goes into here ---------+
由于p
未初始化,因此尝试使用它存储值时未定义行为。
未初始化的行为相当令人讨厌(我的一个更低调的断言)。
可以完美地运作。它似乎工作但腐败的东西。它可能会使您的代码崩溃。它可能会影响您的代码,从而在三天后出现问题。它可能会使你的CPU陷入赤裸裸的奇点,带走你和你的家人。
它可能涉及生产鼻子恶魔和/或空气传播的猪: - )
底线是你不应该这样做。
从您的问题来看,您似乎认为*p = 13;
使p
指向值13
。情况并非如此,特别是因为文字13
实际上不可寻址。执行此操作的代码类似于:
int xyzzy = 13; // xyzzy IS addressible,
int *p = &xyzzy; // so make p point at it.
再次,以图形方式:
xyzzy
+---+ +----+
| p | --> points to xyzzy | 13 |
+---+ +----+
这会将p
设置为指向包含13的整数xyzzy
。
答案 1 :(得分:4)
首先解释一下:局部变量未初始化。如果声明变量,则其值将是不确定的。使用未初始化的局部变量会导致undefined behavior。
然后问你的问题:你说
那么为什么我们不能马上指向第二行的整数值(例如13)。
但这不是第二行实际上在做的事情。假设p
已经 指向某个有效的内存区域,然后取消引用指针以将值13
写入该内存区域。如果指针p
是局部变量并且尚未初始化为实际指向任何位置,那么它实际上将包含一个看似随机的值,该值将是它指向的地址。
答案 2 :(得分:1)
int* p;
上述行的含义是p is a pointer to integer
。但是因为我们还没有定义p本身具有什么地址,即我们还没有真正定义p指向的确切位置。我们所知道的是它所拥有的地址(或将来会保留的地址)实际上是整数的地址。所以现在,p指向任何东西,我们无法确定它。
现在你做的时候
*p = 3;
由于此时p中的地址并非由我们指定,因此p很可能指向无法写入的地址。所以行为几乎没有定义。
你应该做的是
int myInt;
int* p;
p = &myInt;
*p = 3;
上面代码的作用是,它使p保存变量myInt
的地址。然后,写入该地址。
你还能做什么呢
int* p;
p = (int *)malloc(sizeof(int));
我不确定你是否熟悉malloc(别担心,你会迟到)。但它的作用是,它为p提供了一块内存(等于整数的大小),现在p指向那个特定的内存块。现在,我们不需要知道该内存块中包含的确切内容,但我们需要知道的是,已经分配给我们的内存可以在没有任何未定义的行为的情况下写入。
干杯