【问题标题】:What is the opposite of calloc in CC中calloc的反义词是什么
【发布时间】:2014-05-04 01:48:11
【问题描述】:

这不仅仅是一个有趣的问题。 :-)

我希望在 C 中初始化一个数组,而不是用calloc 将数组清零。我想将所有元素设置为一个。有没有一个函数可以做到这一点?

我用我上面的问题在谷歌搜索,没有答案。希望你能帮帮我!仅供参考,我是一年级 CS 学生,刚开始用 C 编程。

【问题讨论】:

  • 不,没有这样的事情。也没有一个函数可以将所有元素设置为 ttwo 或三个等。
  • 也许“相反”不是您想要的。也许:“有没有 calloc() 的变体可以将数据初始化为非零值?”
  • 没有。在正常的 C 开发中,它实际上是不需要的。但是您可以编写一个,首先使用 malloc,然后使用 for(;;)-loop 来填充分配的内存间隔。
  • @JonathanLeffler 好电话。但这也没有给我在谷歌上的答案。我想我是 StackOverflow 上唯一对此感到好奇的人。
  • 我已经用 C 语言编码大约 30 年了,AFAICR 我不需要你问的功能。这绝不是说你需要它是错误的。它只是不是通常需要的功能。

标签: c calloc


【解决方案1】:

没有标准的 C 内存分配函数允许您指定分配的内存初始化为 0 以外的值。

你可以很容易地编写一个封面函数来完成这项工作:

void *set_alloc(size_t nbytes, char value)
{
    void *space = malloc(nbytes);
    if (space != 0)
        memset(space, value, nbytes);
    return space;
}

请注意,这假设您要将每个字节设置为相同的值。如果您有更复杂的初始化要求,则需要更复杂的函数。例如:

void *set_alloc2(size_t nelems, size_t elemsize, void *initializer)
{
    void *space = malloc(nelems * elemsize);
    if (space != 0)
    {
        for (size_t i = 0; i < nelems; i++)
            memmove((char *)space + i * elemsize, initializer, elemsize);
    }
    return space;
}

示例用法:

struct Anonymous
{
    double d;
    int    i;
    short  s;
    char   t[2];
};

struct Anonymous a = { 3.14159, 23, -19, "A" };

struct Anonymous *b = set_alloc2(20, sizeof(struct Anonymous), &a);

【讨论】:

  • 谢谢,但既然你这样回答,我就不能再删了。我会接受它,而不是大声笑。在 12 分钟内..
  • 我刚刚在 Xcode 中尝试过 memset。我认为 memset 专用于字符串。因此,Xcode 给了我不好的访问权限。因为我的问题是专门尝试将数组设置为数值。我不能接受你的回答!还是谢谢!
  • 嗯...该代码不应在 Xcode 或其他任何地方触发错误访问。如果你有空间,memset() 应该会成功(除非你在 Linux 上并且遇到了 OOM Killer)。代码不绑定到字符串; memset() 也不是。 mem*() 函数适用于任意内存,而不是空终止字符串。你是编译 32 位还是 64 位?我假设是64位。你要分配多大的空间?低于 2 GiB 还是更大?你检查过你在ulimit -a 的限制下分配了什么吗?
【解决方案2】:

没有这样的功能。您可以结合使用malloc()memset()(用于字符数据)或for 循环(用于其他整数数据)自行实现。

calloc() 函数存在的动力(与malloc() + memset() 相比)是在某些情况下它可以是一个很好的性能优化。如果您要分配大量数据,操作系统可能会为您提供已初始化为零的虚拟地址范围,从而节省您手动将 0 写入该内存范围的额外成本。这可能会大大提高性能,因为在您实际使用这些页面之前,您不需要将所有这些页面分页。

在后台,calloc() 可能看起来像这样:

void *calloc(size_t count, size_t size)
{
    // Error checking omitted for expository purposes
    size_t total_size = count * size;
    if (total_size < SOME_THRESHOLD)  // e.g. the OS's page size (typically 4 KB)
    {
        // For small allocations, allocate from normal malloc pool
        void *mem = malloc(total_size);
        memset(mem, 0, total_size);
        return mem;
    }
    else
    {
        // For large allocations, allocate directory from the OS, already zeroed (!)
        return mmap(NULL, total_size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
        // Or on Windows, use VirtualAlloc()
    }
}

【讨论】:

    【解决方案3】:

    memset 为您服务:

    memset(array, value, length);
    

    【讨论】:

    • ... 但仅当数组是 chars 的数组时才有效
    • 嗯,第一个参数是void*,所以你也可以用其他数组来喂它。 :P 虽然我不保证它会将元素设置为指定的值...但是如果value != 0 ,它肯定会将其设置为0以外的值! :) 哦,你必须将 length 设置为一个特殊值,因为它希望它的长度以字节为单位,而不是“元素数”。是的,也许我可以详细说明一下用法。 :)
    • 是的,它肯定将其设置为 0 以外的值 :) 但是例如,如果 OP 想要一个 int 数组全部设置为 1,那么 @ 987654328@ 只是不这样做,因为 memset 会将 每个 字节设置为 1,而不是每四个字节,这是您需要将 int 设置为 1(假设 32 位整数)。
    • @Gandaro 我在 Xcode 中编码,如果这样做,Xcode 会抛出错误的访问断言。仅供参考。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-04
    • 2014-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多