最近,我很高兴向C编程初学者介绍了指针,并偶然发现了以下困难。如果您已经知道如何使用指针,这似乎根本就不是问题,但是请尝试以清晰的心态看下面的示例:
int foo = 1;
int *bar = &foo;
printf("%p\n", (void *)&foo);
printf("%i\n", *bar);
对于绝对的初学者来说,输出结果可能令人惊讶。在第2行中,他/她刚刚声明* bar为&foo,但是在第4行中,结果表明* bar实际上是foo而不是&foo !!
您可能会说,造成混淆的原因是*符号的含糊之处:在第2行中,它用于声明指针。在第4行中,它用作一元运算符,用于获取指针指向的值。两种不同的东西,对不对?
但是,这种“解释”根本没有帮助初学者。它指出了细微的差异,从而引入了一个新概念。这不是正确的教学方法。
那么,克尼根和里奇如何解释呢?
一元运算符*是间接或取消引用运算符;当应用于指针时,它访问指针指向的对象。[…]
指针ip的声明
int *ip
旨在用作助记符;它表示该表达式*ip
是一个int。变量声明的语法模仿可能出现该变量的表达式的语法。
int *ip
应该读成“ *ip
会返回int
”?但是,为什么声明之后的赋值不遵循该模式呢?如果初学者想初始化变量怎么办?int *ip = 1
(读取:*ip
将返回int
和,int
则返回1
)将无法正常工作。概念模型似乎并不连贯。我在这里想念什么吗?
编辑:它试图在这里总结答案。
*
声明中的标记是一个含义为“声明指针”的标记,在表达式中,它是解引用运算符,并且这两个代表着碰巧具有相同符号的不同事物。 (与乘法运算符相同-相同的符号,不同的含义)。这令人困惑,但是与实际情况不同的任何事情都会变得更糟。
int* bar
使它变得更加明显,即星形实际上是类型的一部分,而不是标识符的一部分。当然,这会使您遇到诸如的不直观的问题int* a, b
。
*
根据上下文,可以有两种不同的含义。就像同一字母的发音会因其所用的单词而有所不同一样,这使得学习多种语言变得困难。如果每个概念/操作都有其自己的符号,那么我们将需要更大的键盘,因此,在有意义的情况下,这些符号将被回收。
int* p
)上强调星号,同时警告您的学生在涉及指针时不要在同一行中使用多个声明。当学生完全理解了指针的概念后,请向学生说明int *p
is语法是等效的,然后使用多个声明说明问题。