【问题标题】:Difference between malloc and calloc in this case?在这种情况下 malloc 和 calloc 之间的区别?
【发布时间】:2020-07-15 11:22:01
【问题描述】:

这是用 C 语言将两个方阵相乘的代码。

void multiply()函数中使用malloccalloc有什么区别? 使用malloc 时,我得到了垃圾值,但calloc 提供了正确的答案。 只有第一行在输出垃圾值,那么与calloc 相比,malloc 在堆中分配空间的方式是否存在问题?

#include <stdio.h>
#include <stdlib.h>

int *getArray(int);
void display(int *, int, int);
void multiply(int *, int *, int);

int main() {
    int n;
    printf("enter dimension of square matrix:\n");
    scanf("%d", &n);
    int *arr1;
    int *arr2;
    arr1 = getArray(n);
    display(arr1, n, n);
    printf("\n now give input for next array");
    arr2 = getArray(n);
    display(arr2, n, n);
    printf("\n\n\n");
    multiply(arr1, arr2, n);
    return 0;
}

int *getArray(int n) {
    int *arr = (int *)malloc(n * n * sizeof(int));
    printf("\n");
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            scanf("%d", (arr + i * n + j));
        }
    }
    /*for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            printf(" %d ", *(arr + i * n + j));
        }
        printf("\n");
    }*/
    return arr;
}
    
void display(int *arr, int row, int col) {
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++) {
            printf(" %d ", *(arr + i * row + j));
        }
        printf("\n");
    }
}

void multiply(int *arr1, int *arr2, int n) {
    int *arr = (int *)calloc(n * n, sizeof(int));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            for (int k = 0; k < n; k++) {
                *(arr + i * n + j) += (*(arr1 + i * n + k)) * (*(arr2 + k * n + j));
            }
        }
    }
    printf("product of above matrices = \n\n");
    display(arr, n, n);
}

【问题讨论】:

  • 使用malloc(),分配的内存没有初始化;使用calloc(),分配的内存被初始化为所有字节为零。
  • 在您的情况下,初始化内存时没有功能差异。但是在这里使用calloc 意味着calloc 将不必要的设置为零。
  • 这能回答你的问题吗? Difference between malloc and calloc?
  • calloc(n*n,sizeof(int) 不像malloc(n*n*sizeof(int)) 那样容易溢出大小计算。最好将malloc(sizeof(int)*n*n*)malloc() 一起使用。
  • @chux-ReinstateMonica:实际上,如果n * n 超出int 类型的范围,这两个调用都会出现问题,它们只是以不同的方式失败。 malloc(sizeof(int) * n * n) 肯定更好,calloc((size_t)n * n, sizeof(int)) 也是可取的。

标签: c malloc calloc


【解决方案1】:

假设大小计算准确,使用 malloc()calloc() 分配内存之间的唯一功能区别是后者将块初始化为所有位 0,而前者不会。

所有位 0 表示数组中的所有 int 值都初始化为 0

multiply 函数中的内部循环仅增加行i 和列j 的元素,因此该函数依赖于将数组元素隐式初始化为0。calloc() 这样做,但不是@ 987654329@ 所以你肯定需要使用calloc()

还要注意这些备注:

  • display 中,ij 列矩阵元素的偏移量的计算应该是printf(" %5d ", *(arr + i * col + j));
  • multiply 应该返回 arr 并且应该在 main 函数中调用 display()
  • 您应该检查scanf()malloc() and calloc()` 失败
  • 你应该释放分配的内存
  • 指向未被函数修改的对象的指针参数应使用const 限定,以便可以使用指向const 对象的指针调用函数。

这是修改后的版本:

#include <stdio.h>
#include <stdlib.h>

int *getArray(int);
void display(const int *, int, int);
int *multiply(const int *, const int *, int);

int main() {
    int n;
    printf("enter dimension of square matrix:\n");
    if (scanf("%d", &n) != 1)
        return 1;
    printf("\n now give input for the first array");
    int *arr1 = getArray(n);
    if (!arr1)
        return 1;
    display(arr1, n, n);
    printf("\n now give input for the second array");
    int *arr2 = getArray(n);
    if (!arr2)
        return 1;
    display(arr2, n, n);
    printf("\n\n\n");
    int *arr = multiply(arr1, arr2, n);
    if (!arr)
        return 1;
    printf("product of above matrices = \n\n");
    display(arr, n, n);
    free(arr1);
    free(arr2);
    free(arr);
    return 0;
}

int *getArray(int n) {
    int *arr = malloc(sizeof(int) * n * n);
    if (arr == NULL)
        return NULL;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (scanf("%d", (arr + i * n + j)) != 1) {
                free(arr);
                return NULL;
            }
        }
    }
    return arr;
}
    
void display(const int *arr, int row, int col) {
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++) {
            printf(" %5d ", *(arr + i * col + j));
        }
        printf("\n");
    }
}

int *multiply(const int *arr1, const int *arr2, int n) {
    int *arr = calloc((size_t)n * n, sizeof(int));
    if (arr == NULL)
        return NULL;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            for (int k = 0; k < n; k++) {
                *(arr + i * n + j) += (*(arr1 + i * n + k)) * (*(arr2 + k * n + j));
            }
        }
    }
    return arr;
}

【讨论】:

  • 使用const有什么作用?另外,谢谢@chqrlie 的回答。
  • @SiddharthKolipara:在函数定义中,指向未被函数修改的对象的指针参数应该是 const 限定的,因此可以使用指向 const 对象的指针调用函数。例如strcpy()被声明为char *strcpy(char *s1, const char *s2);,因为s2指向的数组内容没有被修改,但是s1指向的目标数组是,并且被返回。
猜你喜欢
  • 2016-07-10
  • 2018-10-09
  • 2010-12-05
  • 2021-05-23
  • 2018-06-24
  • 1970-01-01
  • 2020-12-02
  • 1970-01-01
相关资源
最近更新 更多