memset 将某些元素设置为*几乎*零或 nan

And*_*dyT 2 c windows-subsystem-for-linux

我有一行memset(C, 0, N*M);,其中 C 是双精度矩阵。(我正在使用 WSL。)

但是,如果我查看 gdb,矩阵中的某些元素将设置为其中之一-nan(0xffffffffffff8),而其他元素将设置为例如9.0096750001652956e-314

第一个没有给出任何错误,但 a+=似乎没有改变任何东西(或者至少似乎没有使 nan 的东西消失),而第二个是一个问题,如果元素没有改变或只改变有+= 0,因为比较if (0 == C[i][j])失败。

如果我手动将值设置为 0,则根本不会出现这些问题。

这是 WSL 的事情,还是有什么memset我不明白的事情?

chq*_*lie 5

您没有完全初始化矩阵:memset()需要多个字节。假设矩阵布局是线性的,无论是一维还是二维,您应该清除sizeof(double) * N * M字节。

如果您的矩阵定义为二维数组,您可以编写:

#define N 10
#define M 20
        double C[N][M];
        memset(C, 0, sizeof C);
Run Code Online (Sandbox Code Playgroud)

如果矩阵作为函数参数接收,您实际上得到一个指针,所以您必须更加小心:

void clear_matrix(double C[N][M]) {
    memset(C, 0, sizeof(*C) * N);
}
Run Code Online (Sandbox Code Playgroud)

或者可能更具可读性:

void clear_matrix(double C[N][M]) {
    memset(C, 0, sizeof(C[0][0]) * N * M);
}
Run Code Online (Sandbox Code Playgroud)

或者简单地按照 Lundin 的建议,但如果矩阵元素类型发生变化,则可能会中断:

void clear_matrix(double C[N][M]) {
    memset(C, 0, sizeof(double[N][M]);
}
Run Code Online (Sandbox Code Playgroud)

但请注意,这memset()会将矩阵数据清除为所有位零,如果系统使用 IEEE-754 表示形式,则将值设置double+0.0,但不完全可移植。可移植版本将使用嵌套循环,并且如果适合目标系统,良好的编译器将生成相同的调用或内联代码:memset

#include <stddef.h>

#define N 10
#define M 20

void clear_matrix(double C[N][M]) {
    for (size_t i = 0; i < N; i++) {
        for (size_t j = 0; j < M; j++) {
             C[i][j] = 0.0;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)