【问题标题】:C - How to use own value (instead of 0) with callocC - 如何在 calloc 中使用自己的值(而不是 0)
【发布时间】: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)看我的回答。

标签: c initialization calloc


【解决方案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:你们会将代码的调试版本发送给最终客户吗?
    猜你喜欢
    • 2021-09-18
    • 2021-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-18
    • 1970-01-01
    相关资源
    最近更新 更多