【问题标题】:Printing the value of memory allocated by calloc not initialized to zeroed打印 calloc 分配的内存值未初始化为零
【发布时间】:2021-11-20 22:40:11
【问题描述】:

当我尝试使用 calloc 而不是 malloc 时,我对正在发生的事情感到困惑。我的理解是calloc分配内存并将每个地址的值初始化为零,而malloc只是分配内存。但是,当我尝试打印每个地址的值时,我希望 calloc 的值为零,malloc 的随机字符 - 但它们不是......无论我做什么,它们都是相同的。

typedef struct {
    char* text;
    void* obj;
} statement_t;

void* stalloc() {
    return calloc(1, MODEL_OBJ_CAPACITY);
    // return malloc(MODEL_OBJ_CAPACITY); Also used this
};

statement_t NewStatement(char* text) {
    statement_t statement;
    statement.text = text;
    statement.obj = stalloc();

    return statement;
};


int main(void) {
    statement_t statement = NewStatement("CREATE job Manager");

    for(int n = 0; n < 10; ++n) {
        printf("statement[%d]: %c\n", n, (char)&statement.obj[n]); // Note I've tried a number of ways to print this but they always end up being the same
    }

    ...
}

calloc 的输出:

statement: CREATE job Manager 0x7fb127405c60 8
statement[0]: `
statement[1]: a
statement[2]: b
statement[3]: c
statement[4]: d
statement[5]: e
statement[6]: f
statement[7]: g
statement[8]: h
statement[9]: i

malloc 的输出:

statement: CREATE job Manager 0x7f8becc05c60 8
statement[0]: `
statement[1]: a
statement[2]: b
statement[3]: c
statement[4]: d
statement[5]: e
statement[6]: f
statement[7]: g
statement[8]: h
statement[9]: i

如您所见,它们是相同的......我错过了什么?

【问题讨论】:

  • statement_t 是什么?
  • MODEL_OBJ_CAPACITY 是什么? calloc() 分配了多少非常重要。
  • 我不认为这些是随机值 - 注意第一个值对应于0x60,下一个对应于0x61,等等。
  • 这段代码是非法的,你不能在标准 C 中的 void * 上使用 []。请以一致模式调用编译器,以避免在编译时应该拒绝的程序上因运行时错误而浪费时间
  • @M.M 提出了一个很好的观点,解决编译器已经发现的问题是浪费大家的时间。为了防止这种情况,我建议关注What compiler options are recommended for beginners learning C? 突然我们得到 "ISO C 不允许额外的 ';'在函数之外“”错误:在算术中使用的“void *”类型的指针”和大量其他错误,其中大部分是不言自明的。

标签: c pointers dynamic-memory-allocation


【解决方案1】:

obj 的类型为 void*。 C 标准不允许对 void 指针进行任何指针运算。无法索引void *

它是gcc 扩展,不可移植。

试试:

printf("statement[%zu]: %d\n", n, ((char *)statement.obj)[n]);

    int c;

    for(size_t n = 0; n < 10; ++n) {
        c = ((char *)statement.obj)[n];
        printf("statement[%zu]: %s : %d (0x%02x)\n", n, (c >= 32 && c <= 127) ? (char []){'\'', c, '\'', 0} : "not printable", c, c ); 
    }

【讨论】:

  • (char *)statement.obj 周围有一组括号有什么作用?
  • 它显示了我索引char *指针的编译器
  • 好的,这对 calloc 的预期效果是,它为每个打印 0,但在使用 malloc 时也是如此。那是对的吗?我虽然 malloc 分配但在这些内存块中会有字符,而 calloc 分配并将它们初始化为零,因此它们打印 print 0s
  • @Garrett 与 malloc 未确定。任何值都是可能的。没有规则。
  • 啊,好吧,换句话说,打印出来的结果是一样的没关系,而且在使用malloc之后的未来打印可能最终会达到我对这个问题的预期?
【解决方案2】:

您没有正确打印:

printf("statement[%d]: %c\n", n, (char)&statement.obj[n]); 

您正在尝试打印数组中每个字节的 地址,而不是字节本身。此外,通过使用%c,您将打印与每个字节值相关联的字符,而不是实际值。

首先将void * 转换为char *,然后索引数组。另外,使用%d 打印每个字节的值:

printf("statement[%d]: %d\n", n, ((char *)statement.obj)[n]); 

【讨论】:

  • OP 可能会将printfscanf 混淆。 %d%c 格式说明符需要scanf 中的指针值,但printf 中不需要。
  • 我原来有这个,它给出了错误incomplete type is not allowed
  • @dbush 你如何索引 void * (gcc 除外)
  • 试图用%c 打印值0 的字符定义不明确
  • @0___________ 一定是忽略了指针类型。固定。
猜你喜欢
  • 2021-01-08
  • 1970-01-01
  • 1970-01-01
  • 2020-08-21
  • 2021-10-16
  • 2021-01-14
  • 2022-09-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多