C - 如何在 calloc 中使用自己的值(而不是 0)

Posted

技术标签:

【中文标题】C - 如何在 calloc 中使用自己的值(而不是 0)【英文标题】:C - How to use own value (instead of 0) with calloc 【发布时间】:2015-10-16 17:36:29 【问题描述】:

在 C 中当我们使用 calloc 方法时;所有保留的内存将被初始化为0

有没有办法用另一个值来初始化它而不遍历所有值? 例如:

int* example = calloc(100,sizeof(int));

这将创建一个包含 100 个零的数组,但我希望它是(例如)100 个。

【问题讨论】:

malloc 它并在 malloc 的块上调用 memset 假设我得到了一个结构体的初始化“对象”(示例当然是 struct* 类型)。是否会为 100 个内存位置中的每一个复制这个“对象”? “众所周知”这一短语声称有问题的另一个例子。内存使用all bits zero 初始化,它不一定与0/0.0 或空指针相同。 callocmemset 一样,对块的结构一无所知。而C 没有方法calloc 是一个函数 您的意思是如果机器上的 00000000 表示例如字符“a”。然后 calloc 会将所有内容初始化为 'a'? 1) 请使用@ 向评论者致辞,否则您的评论可能会被忽视。 2)看我的回答。 【参考方案1】:

callocmemset 一样不知道存储在分配块中的数据结构。实际上,除了char 类型的数组之外,将memset0 以外的任何东西一起使用几乎没有什么用处。请注意,calloc 在功能上 malloc 加上memset(..., 0),但在某些实现中可能要快得多。

按照标准,calloc不存储0,而是sets all bits zero。这不一定会导致浮点 0.0 或空指针常量,因为它们可能具有其他二进制表示。然而,对于整数类型,0 的所有位都为零,因此 this 有效。

但仅适用于0,因为在大多数(如果不是全部)现代平台上,整数至少使用 2 个字节,所以如果您按字节设置,您将触及同一整数的不同字节。试试memset(..., 3),对于 32 位 int,你会读到 0x03030303,对于 64 位 0x0303030303030303

要设置已分配数组的结构化值,无法使用循环:

// here we use int, but that can also be float or a struct
int *a = malloc(sizeof(*a) * 5);
if ( a != NULL ) 
    for ( size_t i = 0 ; i < 5 ; i++)
        a[i] = 1;    // for a struct use a compound literal or set per field

    ...
    free(a);

您首先不应该担心性能。上面的模式很可能会被您的编译器识别并被高度优化的代码所取代,这些代码将与memset(但不是calloc)一样快(如果不是更快的话)。

【讨论】:

"calloc 只是malloc 加上memset(..., 0)"并非如此。示例Why malloc+memset is slower than calloc? @chux:我编辑了。然而,这超出了抽象机器的范围。 可能也想找出一些错别字。【参考方案2】:
int* example;
example=malloc(100*sizeof(int));    // allocate memory to store 100 int
if(example)
    memset(example,1,100*sizeof(int));  // initialize it with value 1

编辑

尽管有人赞成上述代码,但是(我犯了一个错误,现在正在纠正它) - 上面的例子是错误的 .As from manpage -

memset() 函数用常量字节 c 填充 s 指向的内存区域的前 n 个字节。

所以,上面的代码不会像预期的那样工作。

// allocate memory as you do 
for(int i=0;i<100;i++)
      example[i]=1;

 free(example);

这样就可以了。

【讨论】:

【参考方案3】:

让编译器弄清楚如何通过使用memcpy() 复制大卡盘来快速完成它 - 当然是优化的函数调用。

int *alloc_int_preset(int value, size_t count) 
  int *begin = malloc(sizeof *begin * count);
  if (begin && count) 
    count--;
    size_t n = 1;
    *begin = value;
    int *p = &begin[1];  // place to copy to
    while (count > 0) 
      size_t i = min(count, n);
      // perform memcpy() in ever doubling in size blocks
      memcpy(p, begin, sizeof *p * i);
      p += i;  // advance i `int`s
      n += i;  // advance i
      count -= i;
    
  
  return begin;

第一次循环,memcpy(&amp;begin[1], begin, sizeof *p * 1) 第二次循环,memcpy(&amp;begin[2], begin, sizeof *p * 2) 第三次循环,memcpy(&amp;begin[4], begin, sizeof *p * 4) 第 4 次循环,memcpy(&amp;begin[8], begin, sizeof *p * 8)

【讨论】:

我闻到了 UB 的潜力。另外我怀疑这真的比for 循环模式快。 @Olaf 用鼻子试着找到它。没有 UB。 这不是你想的那样。你不检查malloc的结果(我只是写了“潜力”,不是它在那里) @Olaf 我认为assert(begin) 会这样做。 @ameyCU:你们会将代码的调试版本发送给最终客户吗?

以上是关于C - 如何在 calloc 中使用自己的值(而不是 0)的主要内容,如果未能解决你的问题,请参考以下文章

零基础学C语言内存知识总结:memset函数和calloc函数

C语言中动态内存分配函数的用法及作用?(比如malloc,calloc,realloc等)

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

C ++初始化没有New或Malloc / Calloc /等

Qt Creator - calloc 因内存大而失败

我对 C 上的 malloc() 和 calloc() 感到非常困惑