-3

I want to declare a double type array dynamically, so here is my code

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]);
    }

    ...
}

When I pass a length of 2, the code does not print all 1s. It just prints the following:

7.7486e-304
7.7486e-304

So, what should I do to fix it?

chqrlie
  • 131,814
  • 10
  • 121
  • 189
GoingMyWay
  • 16,802
  • 32
  • 96
  • 149

5 Answers5

8

memset sets bytes. You're trying to set doubles. Just loop from 0 to length and set each one to 1.0:

for (int i = 0; i < length; i ++)
{
    a[i] = 1; // or 1.0 if you want to be explicit
}
anatolyg
  • 26,506
  • 9
  • 60
  • 134
3

memset sets every byte of your array to 1 not every int or double element.

You are trying to set double values (maybe 8 or more bytes.) Your approach will only work for the number 0.0 as it happens to be represented with all bytes 0 on systems that use IEEE-754 floating point formats. Note that this would be non portable as the C Standard allows other representations for floating point values.

If a was pointing to an array of integers, your approach would work for 0 and -1 and some special values such as 0x01010101... But it would still be a non portable approach as it would fail or even invoke undefined behavior on exotic architectures with padding bits or non 2s complement integer representation.

The correct way to initialize the array is an explicit loop like this:

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

The compiler will likely compile this loop into very efficient code.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • -1 would work with integer types but it doesn't work with floating point. IEEE-745 floats are sign-exponent-mantissa; the only difference between 1.0 and -1.0 is the sign bit. The value with all bits set is a NaN. – rici Jul 24 '16 at 08:16
  • @rici: `-1` only works for 2s complement integers and all bits used. For 1s or s/m, it will fail, too. – too honest for this site Jul 24 '16 at 10:48
3

You are confusing setting an array and setting the underlying memory that stores an array.

A double is made up of 8 bytes. You are setting each byte that makes up the double to 1.

If you want to initialise each element of the array to 1.0 then you can use a for(;;) loop or since you do seem to be using C++ you can use a container and use a constructor to initialise each element (if the constructor has the ability) or use an algorithm to achieve the same effect.

graham.reeds
  • 16,230
  • 17
  • 74
  • 137
  • Thank you, and I know what I should do to fix my code now! – GoingMyWay Jul 24 '16 at 08:57
  • There is no requirement for a `double` to consist of 8 bytes. It could be 9, 10 or even 1 (considering a byte on the target has >=64 bits). And OP uses C, not C++ – too honest for this site Jul 24 '16 at 10:44
  • True, there is no requirement to have 8 bytes but most do and in the original post @AlexanderYau had `cout` in his code. Since posting my answer he has gone back and edited it. – graham.reeds Jul 24 '16 at 14:31
1

memset sets 1 byte at a time. Because of that, I recommend that you use a custom function to set an array of any data type to a valid value like the following:

#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;
}
machine_1
  • 4,266
  • 2
  • 21
  • 42
-1

You use memset to set your every bytes of array a.Double variable are 8 bytes,after memset array a every bytes is 1. Function memset is for char array. If you want init your array a you can use a loop(while/for).

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