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
或空指针相同。 calloc
和 memset
一样,对块的结构一无所知。而C 没有方法。 calloc
是一个函数!
您的意思是如果机器上的 00000000 表示例如字符“a”。然后 calloc 会将所有内容初始化为 'a'?
1) 请使用@
向评论者致辞,否则您的评论可能会被忽视。 2)看我的回答。
【参考方案1】:
calloc
和memset
一样不知道存储在分配块中的数据结构。实际上,除了char
类型的数组之外,将memset
与0
以外的任何东西一起使用几乎没有什么用处。请注意,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(&begin[1], begin, sizeof *p * 1)
第二次循环,memcpy(&begin[2], begin, sizeof *p * 2)
第三次循环,memcpy(&begin[4], begin, sizeof *p * 4)
第 4 次循环,memcpy(&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等)