我最近很高兴向C编程初学者解释指针并偶然发现了以下困难.如果你已经知道如何使用指针,它可能看起来似乎不是一个问题,但尝试以清醒的头脑看下面的例子:
int foo = 1;
int *bar = &foo;
printf("%p\n", (void *)&foo);
printf("%i\n", *bar);
Run Code Online (Sandbox Code Playgroud)
对于绝对的初学者来说,输出可能会令人惊讶.在第2行他/她刚刚宣布*bar为&foo,但在第4行结果显示*bar实际上是foo而不是&foo!
您可能会说,混淆源于*符号的模糊性:在第2行中,它用于声明指针.在第4行中,它用作一元运算符,它获取指针指向的值.两件不同的事,对吗?
然而,这种"解释"根本不能帮助初学者.它通过指出一个微妙的差异引入了一个新的概念.这不是教授它的正确方法.
那么,Kernighan和Ritchie是如何解释的呢?
一元运算符*是间接或解除引用运算符; 当应用于指针时,它访问指针指向的对象.[...]
指针ip的声明
int *ip用作助记符; 它说表达式*ip是一个int.变量声明的语法模仿可能出现变量的表达式的语法.
int *ip应该读作" *ip会回来int"吗?但是为什么声明后的作业不遵循这种模式?如果初学者想要初始化变量怎么办?int *ip = 1(阅读:*ip将返回a int和intis 1)将无法按预期工作.概念模型似乎并不一致.我在这里错过了什么吗?
编辑:它试图在这里总结答案.
我不确定这是否是一个正确的编程问题,但它总是困扰我,我想知道我是否是唯一的.
在最初学习C++时,我理解了引用的概念,但指针让我感到困惑.你为什么问?因为你如何声明一个指针.
考虑以下:
void foo(int* bar)
{
}
int main()
{
int x = 5;
int* y = NULL;
y = &x;
*y = 15;
foo(y);
}
Run Code Online (Sandbox Code Playgroud)
该函数foo(int*)将int指针作为参数.由于我已经声明y为int指针,我可以传递y给foo,但是当我第一次学习C++时,我将*符号与解除引用相关联,因此我认为int需要传递一个解引用.我会试图通过*y进入foo,这显然是行不通的.
用一个单独的运算符来声明指针会不会更容易?(或用于解除引用).例如:
void test(int@ x)
{
}
Run Code Online (Sandbox Code Playgroud) 有没有理由c的语言设计者使用星形来定义指针类型
int* x;
Run Code Online (Sandbox Code Playgroud)
和取消引用指针?
int y = *x;
Run Code Online (Sandbox Code Playgroud)
对两个不同的东西使用相同的字符似乎令人困惑,特别是因为它们总是在相同的上下文中使用.
为什么要用 * 来声明指针?
它删除了间接寻址,但当您声明像 之类的指针时,不会删除任何间接寻址int *a = &b,难道它不应该删除 的间接寻址吗&b?
关于C(以及 C++ 的 C 子集)中指针和数组声明的细节,SO 上有很多问题。
我对为什么更感兴趣。当我们连续声明多个指针/数组时,
为什么必须将*,[]放在每个变量的前面?
int *a, *b;
int c[1], d[1];
Run Code Online (Sandbox Code Playgroud)
为什么我们必须在函数指针中的变量名之后/周围键入内容?
void (*foo_ptr)(int, int);
Run Code Online (Sandbox Code Playgroud)
为什么我们有这个让很多新手感到困惑的功能,甚至编译器也会识别并报告这些东西作为类型的一部分?前任:function foo accepts int** but it was given int*
我想我正在寻找它背后的直觉,导致它以这种方式被创建,以便我可以将它应用于我对语言的理解。现在我只是看不到它......
int value =5;
void testPointer( int* pa, int* pb) {
*pa = *pb +5;
*pb = value;
value += 10;
}
Run Code Online (Sandbox Code Playgroud)
我如何区分两者?我不明白