#include <stdio.h>
#include <stdlib.h>
int main()
{
int *a;
int *b= malloc(sizeof(int)*100);
scanf("%d",&a);
scanf("%d",b);
printf("%d",a);
printf("%d",*b);
return 0;
}
在这段代码中,为什么指向数组的指针不需要scanf的地址位置与普通指针相比?对于指向数组指针的printf,为什么我们必须给出星号符号而不仅仅是指针变量?
在回答这个问题之前,您的代码中存在一个需要修复的错误:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a; // <<< remove * from declaration, such that a is a normal int
int *b= malloc(sizeof(int)*100);
scanf("%d",&a);
scanf("%d",b);
printf("%d",a);
printf("%d",*b);
return 0;
}
所以...
在这段代码中,为什么指向数组的指针不需要scanf的地址位置与普通指针相比?
在scanf
调用中,%d
说明符期望相应的参数具有类型int *
,这是scanf
期望写入整数值的对象的位置。您将b
声明为int *
,因此表达式b
已经具有正确的类型,并且您已将其设置为指向scanf
可以写入整数值的有效内存位置。
在上面的固定代码中,a
的类型为int
,因此我们必须使用表达式&a
来获得int *
值。该值是a
的位置,这是scanf
写入输入整数值的位置。
对于指向数组的指针的printf,为什么我们必须给出星号符号而不仅仅是指针变量?
在printf
调用中,%d
转换说明符期望相应的参数具有类型int
,它是要格式化并写入输出流的整数值。我们已经将a
声明为普通的int
,因此表达式a
已经具有正确的类型,并且表达式的值被格式化并写入输出流。
我们已经将b
声明为int *
,因此它存储地址值,而不是整数。我们必须使用一元b
运算符取消引用*
以获得它指向的整数值。表达式*b
的类型为int
,其值是存储在b
指向的位置的整数值。
而且,只是为了讨厌迂腐,我想要澄清一些术语。 b
没有指向一个数组 - 它指向一个恰好是数组的第一个元素的int
对象(或者在这种情况下,是一个动态分配的缓冲区)。指向数组的指针如下所示:
int a[N];
int (*b)[N] = &a;
要么
int (*b)[N] = malloc( sizeof *b );
我们不打算在这里讨论,因为你不会经常处理指向数组的指针。
您可以将上面的scanf
和printf
调用重写为:
scanf( "%d", &b[0] ); // note & operator in this case
...
printf( "%d", b[0] );
下标表达式a[i]
定义为*(a + i)
- 给定地址a
,从该地址偏移i
元素(不是字节!)并取消引用结果。
由于隐式解引用操作,表达式b[0]
具有类型int
,而不是int *
,这就是为什么我们需要在&
调用中使用scanf
运算符并且在*
调用中不需要printf
运算符。
虽然printf
和scanf
的格式说明符的语法相似,但它们并不完全相同。特别是%d
的scanf
期望int *
,因为它需要变量地址写入,而%d
的printf
期望int
,因为它只需要打印值。
这段代码的问题与a
和b
指出的问题无关,而是如何在printf
和scanf
调用中使用它们。
看每一行:
scanf("%d",&a);
这是无效的,因为%d
的scanf
格式说明符需要int *
但你传递的是int **
。
scanf("%d",b);
这是有效的,因为b
是一个int *
。它会将int
写入数组的第一个元素。
printf("%d",a);
这是无效的,因为%d
的printf
格式说明符需要int
但你传递的是int *
。
printf("%d",*b);
这是有效的,因为*b
是一个int
。它将打印数组的第一个元素。
你的代码实际上有一个拼写错误,如果你像这样使用“int a”,它只会这样工作:
int a;
int *b= (int *)malloc(sizeof(int)*100);
scanf("%d",&a);
scanf("%d",b);
printf("%d",a);
printf("%d",*b);
在这种情况下应该清楚:scanf总是需要一个指针,因此你使用&address运算符表示a而不是b表示已经是指针。对于printf,你需要取消引用b指针,而a已经是int。
如果你坚持使用“int * a”你必须写
int *a;
int *b= (int *)malloc(sizeof(int)*100);
scanf("%d",a);
scanf("%d",b);
printf("%d",*a);
printf("%d",*b);
正如你所看到的那样,指针的处理方式也相同。但是,* a指针未定义(指向“无处”),因此在scanf中使用时可能会崩溃。