我编写了一个简单的代码来创建一个指向整数的指针数组,然后用scanf填充它,而我使用k& R书来做这些事情这次我尝试使用malloc函数但遇到了一个奇怪的问题 这是代码:
#include<stdio.h>
#include<stdlib.h>
#pragma warning(disable:4996)
int getArr(int **myArr);
void print(int *myArr, int n);
int main() {
int *myArr, n;
n = getArr(&myArr);
print(myArr, n);
return 0;
}
int getArr(int **myArr) {
int n;
scanf("%d", &n);
*myArr = (int *)malloc(n * sizeof(int));
for (int i = 0; i < n; i++)
scanf("%d", myArr+i); /* here if i put &(*myArr)[i] will work correctly */
return n;
}
void print(int *myArr, int n) {
while (n-- != 0) {
printf("%d\t", *myArr);
myArr += 1;
}
return;
}
但这两种阅读输入有什么区别?
答案 0 :(得分:1)
%d
的{{1}}格式说明符需要scanf
。
表达式int *
的类型myArr+i
与预期的不匹配,而int **
(或者&(*myArr)[i]
)具有正确的类型*myArr+i
答案 1 :(得分:0)
因为您需要将指针的值更新为您正确执行的过程:
*myArr = (int *)malloc(n * sizeof(int));
(除非您不应在C中转换malloc
的返回值)
但是之后*myArr
是指向扫描的指针。 myArr
是指针上的指针。因此,您需要继续取消引用myArr
scanf("%d", (*myArr)+i);
答案 2 :(得分:0)
问题出在getArr()
函数中,因为myArr
是双指针&amp;扫描数据时,您应使用(*myArr) + i)
而不是myArr + i
。 myArr
函数中也未初始化main()
。
这是经过修改的
int getArr(int **myArr) {
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
myArr[i] = malloc(sizeof(int));/*allocate memroy here */
scanf("%d", (*myArr) + i);
}
return n;
}
答案 3 :(得分:0)
您的代码:
int getArr(int **myArr) {
int n;
scanf("%d", &n);
*myArr = (int *)malloc(n * sizeof(int));
for (int i = 0; i < n; i++)
scanf("%d", myArr+i); /* here if i put &(*myArr)[i] will work correctly */
return n;
}
您的内存布局如下所示:
myArr (a pointer who lives on the stack in main()
|
| (points to)
V
[XXXX XXXX XXXX XXXX] (allocated by malloc)
4 X一起表示一个整数,因此这是一个序列的数组。取消引用myArr时,会得到指向数组开头的指针。当您索引THAT指针时,您将获得数组中的元素。
您的代码没有这样做:
myArr+i
这是将myArr视为指向数组的指针,而不是指向指针的指针。当您提供myArr + i时,您实际上是这样做的:
myArr --------------------> [WRITE HERE]
|
|
V
[XXXX XXXX XXXX XXXX]
(想象一下,内存从左到右,一行一行,所以数组是#34;远离#Arr,而[WRITE HERE]更接近它。通过添加到myArr指针,你&# 39;重新进入无效的内存区域.myArr字面上在main中保存一个地址(因为你最初声明它的位置,并将其地址传递给此函数。)当你添加它时,你正在某处计算一个地址在主堆栈框架中,scanf将其视为指向int的指针,并将某些字节写入堆栈中。
您的替代语法正在做一些不同的事情:
&(*myArr)[i]
取消引用myArr,获取malloc数组的开头,然后索引到第i个偏移int的数组中,然后获取该int的地址并将其传递给scanf。
这样做的原因是[]的优先级高于&amp;,因此它等同于:
&((*myArr)[i])
根据此方案,这是访问记忆的正确方法。
了解这一点很好,但是K&amp; R C风格编码的时代正在消退,特别是在c ++代码库中,因为使用像这样的原始指针的危险和容易出错的性质(就像你和#39幸运的是,已被c ++惯用语取代,以帮助封装内存访问并减少难以理解的错误。