AndyT
AndyT

Reputation: 45

memset sets some elements to *almost* zero or nan

I have the line memset(C, 0, N*M);, where C is a matrix of doubles. (I am using WSL.)

However if I look in gdb, certain elements in the matrix are set to either -nan(0xffffffffffff8) and others are set to for example 9.0096750001652956e-314.

The first one doesn't give any errors but a += doesn't seem to change anything (or at the very least doesn't seem to make the nan thing disappear), while the second is an issue if the element is not changed or only has += 0, as the comparison if (0 == C[i][j]) then fails.

If I set the values to 0 manually, then these issues do not arise at all.

Is this a WSL thing, or is there something about memset that I do not understand?

Upvotes: 2

Views: 356

Answers (2)

chqrlie
chqrlie

Reputation: 144951

You do not fully initialize the matrix: memset() expects a number of bytes. Assuming the matrix layout is linear, either 1D or 2D, you should clear sizeof(double) * N * M bytes.

If your matrix is defined as a 2D array, you could write:

#define N 10
#define M 20
        double C[N][M];
        memset(C, 0, sizeof C);

If the matrix is received as a function argument, you actually get a pointer, so you must be more careful:

void clear_matrix(double C[N][M]) {
    memset(C, 0, sizeof(*C) * N);
}

or possibly more readable:

void clear_matrix(double C[N][M]) {
    memset(C, 0, sizeof(C[0][0]) * N * M);
}

or simply, as suggested by Lundin, but likely to break if the matrix element type changes:

void clear_matrix(double C[N][M]) {
    memset(C, 0, sizeof(double[N][M]);
}

Note however that memset() will clear the matrix data to all bits zero, which sets the double values to +0.0 if the system uses IEEE-754 representation, but is not fully portable. A portable version would use a nested loop and a good compiler will generate the same memset call or inline code if appropriate for the target system:

#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;
        }
    }
}

Upvotes: 5

Lundin
Lundin

Reputation: 214300

The M*N is the number of items (doubles) but memset expects the number of bytes. For an array double C[M][N], you need to do memset(C, 0, sizeof(C));.

Upvotes: 2

Related Questions