【问题标题】:Explanation about types and variables used in a malloc code关于 malloc 代码中使用的类型和变量的说明
【发布时间】:2019-10-31 09:28:46
【问题描述】:

我需要对这段特定代码中的一些命令进行一些解释:

#inlcude <stdlib.h>
#define PTRS 5

char *p[PTRS];

size_t nbytes = 10;
int i;
/* Allocating memory */
for (i=0; i<PTRS; i++){
    printf("malloc of %10lu bytes ", nbytes);

    if ((p[i] = (char *)malloc(nbytes)) == NULL){
        printf("failed\n");
    } else {
        printf("succeeded\n");
    nbytes *= 100;
}
/* Free the memory allocated */
for (i=0; i<PTRS; i++){
    if(p[i]){
        free(p[i]);
        p[i] = NULL;
    }
}

第一个是
char *p[PTRS];
此行是声明一个指向数组的指针,还是声明一个指向char的指针数组?
p[i] = (char *)malloc(nbytes)我明白了随着i 的增加,p[i] 将包含一个指向已分配内存的指针,如果它被成功处理,则由 malloc 调用,如果无法准备这样的内存,则 p[i] will beNULL`。
第二个是

if (p[i]){
    free(p[i]);
    p[i] = NULL;
}

这仅在p[i] 有任何值(在本例中为指向内存的指针)时才释放内存。如果我们删除if(p[i]) 并只使用free(p[i]p[i] = NULL 会发生什么?我们可以释放NULL 指针吗?

【问题讨论】:

  • 最后一个问题可以参考this question
  • 给定size_t nbytes,您的printf("malloc of %10lu bytes ", nbytes); 会调用未定义的行为。 size_t 的正确格式字符串是 %zu
  • 顺便说一句,在现代 C 中不鼓励强制转换 malloc(),因为即使 #include &lt;stdlib.h(声明 malloc() 和朋友的标头)也可以强制代码编译,然后常见的结果是未定义的行为。只有在将 void 指针引入语言之前(所以 malloc() 返回 char *)之前的(非常旧的)C 版本中才需要。

标签: c pointers malloc


【解决方案1】:
char *p[PTRS];

等价于

char *(p[PTRS]);

即它是一个指针数组,而不是指向数组的指针。指向数组的指针将是例如

char (*p)[PTRS];

clockwise/spiral rule 可能有助于破译声明。就像使用 https://cdecl.org 等资源一样。


您可以将NULL 指针传递给free(这是一个无操作),因此实际上不需要检查。

根据p 的进一步使用,p[i] = NULL 分配也可能不需要。

【讨论】:

  • 谢谢!而且我刚刚读到free(NULL) 曾经在旧系统上引起一些问题,这就是他们添加检查的原因。
  • @NVA - 如果您设法找到非常旧的编译器和库,这​​只是一个问题。甚至 K&R C(第一版是 1978 年,根据记忆,比第一个 C 标准的批准早了十多年)指定 free(NULL) 无效。在 K&R 第一版之前有一些库会在 free(NULL) 上崩溃,但即使它们的供应商/开发人员也认为这些库是错误,因此您很难找到具有这种行为的 C 编译器和库。
【解决方案2】:

我知道随着 i 的增加,p[i] 将包含一个指向 malloc 调用的分配内存

因此,如果您理解这一点,这意味着 p[i] 作为数组的一个元素具有 char * 类型,因为至少在程序中,在 if 语句中对这种类型的malloc 调用进行了显式转换

 if ((p[i] = (char *)malloc(nbytes)) == NULL){

所以这个声明

char *p[PTRS];

用tyoe char * 声明一个PTRS 元素数组。我建议写这样的声明,如

char * p[PTRS];

在字符'*'之后插入一个空格。

你也可以通过以下方式重写声明

char * ( p[PTRS] );

指向char 类型的PTRS 元素数组的指针以下列方式声明。

char ( *p )[PTRS];

我们可以释放一个 NULL 指针吗?

更准确地说,我们是否可以将函数 free 与空指针一起使用,因为我们没有释放空指针本身,在您的示例的上下文中具有自动存储持续时间。

答案是肯定的,我们可以。使用空指针调用函数不会产生任何影响并且是安全的。

因此这个循环

for (i=0; i<PTRS; i++){
    if(p[i]){
        free(p[i]);
        p[i] = NULL;
    }
}

可以像这样重写

for (i=0; i<PTRS; i++){
    free(p[i]);
    p[i] = NULL;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-04
    • 1970-01-01
    • 2020-07-05
    • 1970-01-01
    • 1970-01-01
    • 2018-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多