Arrays 为什么我们不';在malloc数组的情况下,是否不需要取消引用指针值?
我在试图理解C编译器如何以一种阴暗的方式解释字符数组、字符串、整数和数组时遇到了困难。谢谢你帮我。甚至许多reddit用户也指出,C中的指针在解释命令时有点模糊。 因此,我试图通过一个例子来理解Arrays 为什么我们不';在malloc数组的情况下,是否不需要取消引用指针值?,arrays,c,pointers,memory-management,malloc,Arrays,C,Pointers,Memory Management,Malloc,我在试图理解C编译器如何以一种阴暗的方式解释字符数组、字符串、整数和数组时遇到了困难。谢谢你帮我。甚至许多reddit用户也指出,C中的指针在解释命令时有点模糊。 因此,我试图通过一个例子来理解malloc。但在此之前,这是我的理解。 假设*p是一个变量。然后p保持它指向的地址。 而*p引用地址所持有的值。 在动态分配的情况下, 当我这样做的时候 int *p = (int *)malloc(sizeof(int)*5); //say we want 5 locations // 当用户给出所
malloc
。但在此之前,这是我的理解。
假设*p
是一个变量。然后p保持它指向的地址。
而*p
引用地址所持有的值。
在动态分配的情况下,
当我这样做的时候
int *p = (int *)malloc(sizeof(int)*5); //say we want 5 locations //
当用户给出所有5个值时,手动循环,我输入如下值
scanf("%d", p+i) // as p already holds address, I get that we don't have to provide the & . And i being the iterator.. //
然后用另一个循环打印,这是发生的事情,我不知道为什么
说出用户输入的55,66,77,88,99
当我用这个代码打印时
printf("%d", *p+i); // De-referencing the values in location p by using asterics, + the value of iteration,i //
我得到的值与55,56,57,58,59的值一样疯狂
所以,在互联网的一点帮助下,我尝试了这样的printf代码,效果非常好,但是
我甚至不必取消引用。这到底是为什么让人如此困惑
printf("%d", p[i]); // No asterics used. How does the compiler know I want the value and not the address? as p only should hold the addresses, and *p should give us the values in those addresses //
同样,如果我做了printf(“%d”,*p++)代码>
然后它也能工作。
为什么我不明白C是如何工作的
同样的,如果我尝试做同样的事情,但是这次是用scanf(“%d”,p[I])代码>,然后是语法错误。
我是说为什么
谢谢
假设*p是一个变量
否。变量为p
,其类型为int*
*p
:在地址p
*p+i
解析为(*p)+1
:地址p
处的值,然后将值1
添加到该值中
p[i]
相当于*(p+i)
:地址p+i
处的值,其中p+i
是从p
开始的整数数组的i
第个元素的地址。A.k.A.整数向量中从p开始的i
th元素
*p++
解析为*(p++)
:增加指针p
(即使p
指向下一个元素)并从p
的旧值中获取值
假设*p是一个变量
否。变量为p
,其类型为int*
*p
:在地址p
*p+i
解析为(*p)+1
:地址p
处的值,然后将值1
添加到该值中
p[i]
相当于*(p+i)
:地址p+i
处的值,其中p+i
是从p
开始的整数数组的i
第个元素的地址。A.k.A.整数向量中从p开始的i
th元素
*p++
解析为*(p++)
:增加指针p
(即使p
指向下一个元素)并从p
的旧值中获取值
我认为一个小的可运行代码将帮助您更好地理解,而不是我解释
#include <stdlib.h>
#include <stdio.h>
int main() {
int *p = (int *)malloc(sizeof(int)*5);
int *q = (int *)malloc(sizeof(int)*5);
int i = 0;
int test_val = 100;
for(i = 0; i < 5; i++) {
*(p + i) = test_val;
q[i] = test_val;
test_val = test_val + 10;
}
for(i = 0; i < 5; i++)
printf("p[%d] = %d\n", i, p[i]);
printf("p[i] gives the value in array p at index i \n\n");
for(i = 0; i < 5; i++)
printf("q[%d] = %d\n", i, q[i]);
printf("Note that the values in p and q are equal which means that *(x + 1) and x[i] are 2 ways to access the same values \n\n");
for(i = 0; i < 5; i++)
printf("*p + %d = %d\n", i, *p + i);
printf("*p + i gets value pointed by p and adds i to it in each iteration \n\n");
for(i = 0; i < 5; i++)
printf("*(p + %d) = %d\n", i, *(p + i));
printf("*(p + i) gets value pointed by p + i \n\n");
int *j = (int *)malloc(sizeof(int)*5);
int *k = (int *)malloc(sizeof(int)*5);
int *l = (int *)malloc(sizeof(int)*5);
for(i = 0; i < 5; i++) {
j[i] = test_val;
k[i] = test_val;
l[i] = test_val;
}
printf("(*j)++ = %d\n\n", (*j)++);
printf("*(k++) = %d\n\n", *(k++));
printf("*l++ = %d\n\n", *l++);
for(i = 0; i < 5; i++) {
j[i] = test_val;
k[i] = test_val;
l[i] = test_val;
}
printf("test_val = %d\n\n", test_val);
printf("++(*j) = %d\n\n", ++(*j));
printf("*(++k) = %d\n\n", *(++k));
printf("*++l = %d\n\n", *++l);
return 0;
}
对于scanf问题,scanf始终需要一个指针作为参数。p[I]是(p+I)处的值,因此不正确。理想情况下,您应该使用scanf(“%d”&(p[i])我认为一个小的可运行代码将帮助您更好地理解而不是解释
#include <stdlib.h>
#include <stdio.h>
int main() {
int *p = (int *)malloc(sizeof(int)*5);
int *q = (int *)malloc(sizeof(int)*5);
int i = 0;
int test_val = 100;
for(i = 0; i < 5; i++) {
*(p + i) = test_val;
q[i] = test_val;
test_val = test_val + 10;
}
for(i = 0; i < 5; i++)
printf("p[%d] = %d\n", i, p[i]);
printf("p[i] gives the value in array p at index i \n\n");
for(i = 0; i < 5; i++)
printf("q[%d] = %d\n", i, q[i]);
printf("Note that the values in p and q are equal which means that *(x + 1) and x[i] are 2 ways to access the same values \n\n");
for(i = 0; i < 5; i++)
printf("*p + %d = %d\n", i, *p + i);
printf("*p + i gets value pointed by p and adds i to it in each iteration \n\n");
for(i = 0; i < 5; i++)
printf("*(p + %d) = %d\n", i, *(p + i));
printf("*(p + i) gets value pointed by p + i \n\n");
int *j = (int *)malloc(sizeof(int)*5);
int *k = (int *)malloc(sizeof(int)*5);
int *l = (int *)malloc(sizeof(int)*5);
for(i = 0; i < 5; i++) {
j[i] = test_val;
k[i] = test_val;
l[i] = test_val;
}
printf("(*j)++ = %d\n\n", (*j)++);
printf("*(k++) = %d\n\n", *(k++));
printf("*l++ = %d\n\n", *l++);
for(i = 0; i < 5; i++) {
j[i] = test_val;
k[i] = test_val;
l[i] = test_val;
}
printf("test_val = %d\n\n", test_val);
printf("++(*j) = %d\n\n", ++(*j));
printf("*(++k) = %d\n\n", *(++k));
printf("*++l = %d\n\n", *++l);
return 0;
}
对于scanf问题,scanf始终需要一个指针作为参数。p[I]是(p+I)处的值,因此不正确。理想情况下,您应该使用scanf(“%d”&(p[i]))
“当我使用此代码打印时,printf(“%d”,*p+I);
…我得到的值与55
,56
,57
,58
,59
一样疯狂。”
当您使用*p+i
时,p
首先被解除引用(它获得第一个数组元素的值,即55
),然后i
被添加到值55
*p+i
等于(*p)+i
这就是为什么您会得到以下输出:55
,56
,57
,58
,59
,而不是55
,66
,77
,88
,99
您只需将i
添加到每个迭代中的第一个元素的值中,就永远不会访问以下4个数组元素
“我试过这样的printf
代码,效果很好,但我甚至不需要取消引用….printf(“%d”,p[I]);
”
使用p[i]
时,将在数组的i
第个元素处获得值,因为它在取消引用之前偏移指针本身。它等于*(p+i)
“而且,如果我做了printf(“%d”,*p++);
,那么它也可以工作。”
当您使用*p++
时,p
将被实际解引用,并获得*p
处的值,但此后p
将递增。表示在下一次迭代p
时指向下一个数组元素
循环完成后,p
指向数组上方一点
“如果我尝试做同样的事情,但这次是使用scanf(“%d”,p[I]);
,那么语法错误。我是说为什么?”
对于scanf()
来说,情况有点不同
当您使用scanf(“%d”,p[i])
,p[i]
等于*(p+i)
,因为它也在printf()
调用中,但当您尝试取消引用并获得int
对象而不是指向int
的指针时,这是scanf()
处的%d
所需的,这是一个语法错误
在scanf()
中,%d
需要类型为int*
的参数,而不是int
关于你的主要问题:
“为什么我们不需要取消引用
int *p = ....
p ______
|
\|/
--------------------------
| 55 | 66 | 77 | 88 | 99 |
--------------------------
printf("%d", *p+i); // De-referencing the values in location p by using asterics, + the value of iteration,i //
(*p) + 0 -> 55 + 0 -> 55
(*p) + 1 -> 55 + 1 -> 56
(*p) + 1 -> 55 + 4 -> 59
printf("%d", p[i]); // No asterics used. How does the compiler know I want the value and not the address? as p only should hold the addresses, and *p should give us the values in those addresses //
p[i] -> *((p) + (i)) -> *(p + i)
*(p++) -> p will be incremented but the value of p in the expression will be its value prior to the increment operation which is location of element at `0`th index
-> *(0th location address) -> 55
*(p++) -> p will be incremented but the value of p in the expression will be its value prior to the increment operation which is location of element at `1`st index
-> *(1st location address) -> 66
*(p++) -> p will be incremented but the value of p in the expression will be its value prior to the increment operation which is location of element at `4`th index
-> *(4th location address) -> 99
p[i] -> *((p) + (i)) -> *(p + i)
scanf("%d", &p[i]);
&p[i] -> &(p[i]) -> &(*((p) + (i)) -> ((p) + (i)) -> p + i
| |
Precedence of operator |
[] is higher than |
& operator |
|
The operator & is used to get the address and the operator * is used for dereferencing.
These operators cancel the effect of each other when used one after another.
scanf("%d", &p[i]);
scanf("%d", p + i);