填充整数

时间:2018-04-27 19:25:39

标签: c

我编写了一个简单的代码来创建一个指向整数的指针数组,然后用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;
}

但这两种阅读输入有什么区别?

4 个答案:

答案 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 + imyArr函数中也未初始化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 ++惯用语取代,以帮助封装内存访问并减少难以理解的错误。