calloc 的结果可以分配给什么类型,是指向数组的指针、指向数组中包含的类型的指针,还是其中之一?

问题描述 投票:0回答:1

根据标准(C17草案,7.22.3.2),

calloc

void *calloc(size_t nmemb, size_t size);

“为

nmemb
对象数组分配空间,每个对象的大小为
size
”(并将所有位初始化为零)。

对于

calloc
T
数组,我只见过这样的代码:

T *p = calloc(nmemb, sizeof(T));

但是考虑到

calloc
array 分配空间,以下也应该没问题:

T (*arrp)[nmemb] = calloc(nmemb, sizeof(T));

calloc
的结果可以分配给什么类型,指向数组的指针(类型
T (*)[]
),指向数组中包含的类型的指针(类型
T *
),还是其中之一?

以下代码

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

int main(void) {
    int (*iarrp)[5];
    int *ip;
    float (*farrp)[1];
    float *fp;
    int i;

    iarrp = calloc(5, sizeof(int));
    for (i = 0; i < 5; ++i)
        (*iarrp)[i] = -i;
    ip = calloc(5, sizeof(int));
    for (i = 0; i < 5; ++i)
        ip[i] = i + 100;
    for (i = 0; i < 5; ++i)
        printf("%d: %d, %d\n", i, (*iarrp)[i], ip[i]);

    farrp = calloc(1, sizeof(float));
    (*farrp)[0] = 5.5;
    fp = calloc(1, sizeof(float));
    *fp = 6.6;
    printf("%.2f, %.2f\n", (*farrp)[0], *fp);

    free(iarrp);
    free(ip);
    free(farrp);
    free(fp);

    return 0;
}

使用 GCC (

gcc -std=c17 -pedantic -Wall -Wextra
) 和 MSVC (
cl /std:c17 /Wall
) 对我来说编译得很好,输出符合预期:

0: 0, 100
1: -1, 101
2: -2, 102
3: -3, 103
4: -4, 104
5.50, 6.60

问这个问题的背景是这样的:对于一个类型为

arr
的数组
T[]
,有以下三个表达式

  • arr
    ;类型:
    T[]
    (衰减前),
    T *
    (衰减后)
  • &arr[0]
    ;类型:
    T *
    • 这就是
      arr
      衰减为
  • &arr
    ;类型:
    T (*)[]
    • &
      防止腐烂

前两者具有相同的值。理论上,第三个表达式的值可以与前两个表达式不同,尽管我知道这种情况并不常见。该标准仅保证

(unsigned char *)&arr == (unsigned char *)&arr[0]
成立。

arrays c language-lawyer calloc
1个回答
1
投票

calloc
返回的动态分配内存没有有效类型,根据C 2018 6.5 6。在C语义中,它只是一个可用于任何对象类型的内存区域。

它可以通过使用非字符类型向其中存储值来获取有效类型。

© www.soinside.com 2019 - 2024. All rights reserved.