C中的指针:分配内存与赋值VS分配内存而不赋值

Posted

技术标签:

【中文标题】C中的指针:分配内存与赋值VS分配内存而不赋值【英文标题】:Pointers in C: Allocating memory with value assignment VS allocating memory without value assignment 【发布时间】:2019-09-11 21:48:54 【问题描述】:

只有当我没有为指针分配一些值时,才通过 calloc 分配 Char 指针的内存。

我正在尝试一些简单的示例来更好地理解指针/双指针/三指针/ ...。在编写双指针代码时,我偶然发现了一个非常奇怪的行为。

#define PRINT(X, ...) printf("Address of " X "\n", ##__VA_ARGS__);

...
...

    int i = 0;
    char buf[12];
    char **two_star;

    two_star = calloc(10, sizeof(char*));
    for (i = 0; i < 10 ; ++i)
        two_star[i] = calloc(10, sizeof(char));
        PRINT("two_star[%d]   = %p", i, two_star[i]);
    

    for (i = 0; i < 10 ; ++i)
        two_star[i] = calloc(10, sizeof(char));
        snprintf(buf, 12, "pre_%d_suff", i);
        two_star[i] = buf;
        PRINT("two_star[%d]   = %p   two_star[%d]   = %s", i, two_star[i], i, two_star[i]);
    

对于上述两个 for 循环,我得到以下结果:

对于循环 1:

Address of two_star[0]   = 0xbcc090
Address of two_star[1]   = 0xbcc0b0
Address of two_star[2]   = 0xbcc0d0
Address of two_star[3]   = 0xbcc0f0
Address of two_star[4]   = 0xbcc110
Address of two_star[5]   = 0xbcc130
Address of two_star[6]   = 0xbcc150
Address of two_star[7]   = 0xbcc170
Address of two_star[8]   = 0xbcc190
Address of two_star[9]   = 0xbcc1b0

对于循环 2:

Address of two_star[0]   = 0x7ffcd2238ab0   two_star[0]   = pre_0_suff
Address of two_star[1]   = 0x7ffcd2238ab0   two_star[1]   = pre_1_suff
Address of two_star[2]   = 0x7ffcd2238ab0   two_star[2]   = pre_2_suff
Address of two_star[3]   = 0x7ffcd2238ab0   two_star[3]   = pre_3_suff
Address of two_star[4]   = 0x7ffcd2238ab0   two_star[4]   = pre_4_suff
Address of two_star[5]   = 0x7ffcd2238ab0   two_star[5]   = pre_5_suff
Address of two_star[6]   = 0x7ffcd2238ab0   two_star[6]   = pre_6_suff
Address of two_star[7]   = 0x7ffcd2238ab0   two_star[7]   = pre_7_suff
Address of two_star[8]   = 0x7ffcd2238ab0   two_star[8]   = pre_8_suff
Address of two_star[9]   = 0x7ffcd2238ab0   two_star[9]   = pre_9_suff

这里的问题很明显。在第二个 for 循环中分配的指针都具有相同的地址值。这意味着 two_star[0] 和 two_star[9] 最终是相同的值,因为相同的内存地址最终会被一次又一次地更新。

【问题讨论】:

memcpy 而不是 two_star[i] = buf; 【参考方案1】:

使用strcpy:strcpy(two_star[i], buf); 而不是two_star[i] = buf;,因为在您的情况下,您不会复制字符串,只需将指针two_star[i] 重新分配给buf(这也是内存泄漏,因为您已经丢失了指向已分配内存的指针)。

【讨论】:

这行得通。时间允许时会接受它作为正确答案。【参考方案2】:

使用strcpy(two_star[i], buf); 是不够的。

    char buf[12];
    two_star[i] = calloc(10, sizeof(char));
    // snprintf(buf, 12, "pre_%d_suff", i);
    strcpy(two_star[i], buf);  // bad, trying to put 12 characters into 10
    two_star[i] = buf;

目的地太小了。

相反,代码可以调整大小。

   int size_needed = snprintf(NULL, 0, "pre_%d_suff", i)  + 1;
   two_star[i] = malloc(size_needed);
   snprintf(two_star[i], size_needed, "pre_%d_suff", i);

注意:为简洁起见,省略了错误检查。

【讨论】:

以上是关于C中的指针:分配内存与赋值VS分配内存而不赋值的主要内容,如果未能解决你的问题,请参考以下文章

指针做参数的动态内存分配与二重指针(上)

cpp►动态内存分配与析构之复制构造函数/赋值运算符

C++中内存分配问题

C语言如何给指针分配内存?

C语言 | 每日基础(31)

在c ++中的赋值运算符重载方法中删除旧的动态分配的内存