C、memset一个双数组失败

Posted

技术标签:

【中文标题】C、memset一个双数组失败【英文标题】:C, memset a double array failed 【发布时间】:2016-07-24 07:03:18 【问题描述】:

我想动态声明一个double 类型的数组,所以这是我的代码

void function(int length, ...)

    ...

    double *a = malloc(sizeof(double) * length);
    memset(a, 1, sizeof(double) * length);
    for (int i = 0; i < length; i++)
    
        printf("%f", a[i]);
    

    ...

当我传递2length 时,代码不会打印全1。它只打印以下内容:

7.7486e-304
7.7486e-304

那么,我该怎么做才能解决它?

【问题讨论】:

你为什么要标记这个c?为什么在 C++ 代码中使用malloc memset 设置字节。您正在尝试设置双打。只需从0 循环到length 并将每个设置为1.0 cout 不是c cout 是标准模板库的一部分,因此是 C++。 既然您现在决定使用 C,您可以放弃 malloc - ***.com/questions/605845/… 的演员表 【参考方案1】:

memset 设置字节。您正在尝试设置双打。只需从0 循环到length 并将每个设置为1.0

for (int i = 0; i < length; i ++)

    a[i] = 1; // or 1.0 if you want to be explicit

【讨论】:

注意:处理浮点数时,明确地使用常量总是一个好主意。所以应该是1.0【参考方案2】:

您混淆了设置数组和设置存储数组的底层内存。

double 由 8 个字节组成。您正在将构成双精度的每个字节设置为 1。

如果您想将数组的每个元素初始化为 1.0,那么您可以使用 for(;;) 循环,或者由于您确实使用 C++,您可以使用容器并使用构造函数来初始化每个元素(如果构造函数有能力)或使用算法达到同样的效果。

【讨论】:

谢谢,我知道我现在应该做什么来修复我的代码! double 不需要包含 8 个字节。它可以是 9、10 甚至 1(考虑到目标上的一个字节具有 >=64 位)。并且 OP 使用 C,而不是 C++ 没错,没有要求有 8 个字节,但大多数都需要,并且在原始帖子中@AlexanderYau 在他的代码中有cout。自从发布我的答案后,他就回去编辑了。【参考方案3】:

memset 将数组的每个字节设置为 1 而不是每个 intdouble 元素。

您正在尝试设置 double 值(可能是 8 个或更多字节。)您的方法仅适用于数字 0.0,因为它恰好在使用 IEEE-754 的系统上用所有字节 0 表示浮点格式。请注意,这将是不可移植的,因为 C 标准允许浮点值的其他表示形式。

如果a 指向一个整数数组,您的方法将适用于0-1 以及一些特殊值,例如0x01010101... 但它仍然是一种不可移植的方法,因为它在具有填充位或非 2s 补码整数表示的奇异架构上会失败甚至调用未定义的行为。

初始化数组的正确方法是这样的显式循环:

for (int i = 0; i < length; i++) 
    a[i] = 1.0;

编译器可能会将这个循环编译成非常高效的代码。

【讨论】:

-1 适用于整数类型,但不适用于浮点。 IEEE-745 浮点数是符号-指数-尾数; 1.0 和 -1.0 之间的唯一区别是符号位。设置所有位的值是 NaN。 @rici: -1 仅适用于 2s 补码整数和使用的所有位。对于 1s 或 s/m,它也会失败。【参考方案4】:

memset 一次设置 1 个字节。因此,我建议您使用自定义函数将任何数据类型的数组设置为有效值,如下所示:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void *g_memset(void *dst, void *val, size_t valSize, size_t count);

int main(void)

    double x = 1.0;
    double Array[50];
    g_memset(Array, &x, sizeof(x), 20);      /* set the 1st 20 elements to 1.0 */
    for (int n = 0; n < 20; n++) 
        printf("%.1lf ", Array[n]);
    
    putchar('\n');
    return 0;


void *g_memset(void *dst, void *val, size_t valSize, size_t count)

    char *ptr = (char *)dst;
    while (count-- > 0) 
        memcpy(ptr, val, valSize);
        ptr += valSize;
    
    return dst;

【讨论】:

【参考方案5】:

您使用memset 设置数组a 的每个字节。双变量为8 个字节,在memset 数组a 之后每个字节为1。 函数memset 用于char 数组。 如果你想初始化你的数组a,你可以使用循环(while/for)。

int j;
for(j =  0;i < length;j++)
    a[j] = 1;

【讨论】:

以上是关于C、memset一个双数组失败的主要内容,如果未能解决你的问题,请参考以下文章

使用 memset 和 int 值初始化整数数组 - 失败

c/c++中对于memset的个人理解

memset(ary,0,length) 是一种在双数组中输入零的可移植方式[重复]

结构c内的memset数组

c语言中函数memset()是啥意思?啥功能

C中浮点数组的Memset问题[重复]