准备一叠黄色便利贴、一支铅笔、一块橡皮和一支钢笔。
拿一张便利贴。用水平线将其分开。在上面写上“note #1”pen在顶部。 (此标记是永久性的)。写“7”与pencil在底部。将其粘贴到计算机屏幕的左上角。
该注释表示存储整数值 7 的内存位置。顶部是address。每个地点都有自己唯一的永久地址。底部部分是value正在存储。
拿另一个笔记,将其分成两个区域,并在其上类似地写上“note #2”和“13”。将其粘贴到屏幕上第一个旁边。这是另一个存储整数值的内存位置,这次是 13。
现在再记一下。在注释的“地址”部分写下“注释#3”。在注释的“值”部分写“note #1“(使用铅笔!)。您刚刚创建了一个pointer。将其贴在前两个音符旁边。
现在在另一张纸上写下一些简写:
a int #1
b int #2
p int* #3
这代表了一个符号表. a
, b
and p
是*变量名`。在下一列中,我们有它们的类型,第三列包含它们的地址。
现在让我们做一些 C 语句。
a = 77;
Look up a
在你的符号表中。它是#1。擦掉这张纸条的数值部分并写入77
相反(这就是橡皮擦派上用场的地方)。
b = 2017;
这与上一个完全类似。
a = b;
Look up a
and b
在你的符号表中。他们分别是#1和#2。看看注释#2 在其“值”部分有什么。将该数字复制到注释 #1 的值部分。
*p = 42;
Look up p
在你的符号表中。这是注释#3。现在找到注释#3的值部分写有数字的注释。这就是所谓的操作解引用。它表示为*
在上面的符号中。擦除 value 部分中的所有内容that注意(不是#3,#3 是指着) 和写42
反而。
*p = b;
自己做这件事。这是您应该得到的:
p = &b;
再次抬头看p
and b
在你的符号表中(分别是#3和#2)。现在采取地址部分#2 的操作(即由&
,毫不奇怪,经常被称为地址运算符)并将其复制到价值部分#3(当然删除之前的内容)。
*p = 42;
现在应该很容易了。
现在在 #4 下创建另一个指针。将其归档到符号表中:q
.
q = NULL;
Find q
(这是#4注释)并写下note #0
在价值部分。请注意,没有注释#0。那是一个空指针。它不指向任何地址。
注意:该标准并不强制要求空指针实际表示为 0。它可能是note #99999999
or note #-1
或者其他什么,只要它与所有现有的笔记不同
p = q;
自己做这件事。这是您应该得到的:
*p = 42;
应该发生什么?表面上你应该采取p
(这是#3),找出它指向哪个注释,然后更改该注释。但现在它指向注释#0,并且没有这样的注释。您已调用未定义的行为。 C 标准明确拒绝指定您的程序应该做什么。实际上,它很可能会崩溃,并显示诸如“分段错误(核心转储)”或“程序已停止工作”之类的消息。