-1

So, I have dynamically allocated memory for an array and I want initialize all its values to a specific value (which is an element of an enumeration).

Here's what I've done so far:

    typedef enum{APPLE, BANANA, ORANGE} fruit;
    typedef struct Smoothie Smoothie;
    struct Smoothie {
        fruit* tab;
    };

This is all the structures I've defined so far. Now, to create the "Smoothie", I do the following:

    Smoothie init(size_t n) {
         Smoothie* juice = malloc(sizeof(Smoothie));
         if (juice == NULL) {
             //error msg in case the allocation has failed.
         }
         juice->tab = calloc(n, sizeof(fruit));
         if (juice->tab == NULL) {
              //error msg in case the allocation has failed.
         }
         memset(juice->tab, APPLE, n*sizeof(fruit));
         return *juice;
    }

My question is the following. From what I've been able to read on the internet, I know that calloc() already initializes all the values of the array at 0. In an enumeration, all the elements have a numerical value (by default, my enumeration has the following values: Apple = 0 BANANA = 1 ORANGE = 2). So, since I want to initialize all the values of my array to APPLE, is it very useful to use memset() ?

In other words, what happens if I do not use memset()? How can I be sure that the compiler will understand that the values in my array are fruit variables and not just integers?

PS: I know that I could use a loop ot initilize my array, but the whole point of this is to actually avoid using the loop.

Skyris
  • 155
  • 1
  • 9
  • `memset` would only work here if `sizeof(fruit) == 1`, which is not guaranteed at all. – Ian Abbott Apr 03 '18 at 16:18
  • 1
    `Smoothie init(size_t n)` Hmmm... are you sure that is what you want? I would expect `Smoothie* init(size_t n)` and just `return juice;` – Support Ukraine Apr 03 '18 at 16:22
  • "`Smoothie init(size_t n)` Hmmm... are you sure that is what you want? I would expect `Smoothie* init(size_t n)` and just `return juice`, ? " Yes I am sure. I want the combination, not a pointer to the combination after using the function. (Although I could do it your way, it doesn't really matter). – Skyris Apr 03 '18 at 16:26
  • 3
    `Smoothie init(size_t n)` would be fine if `juice` was a local variable of type `Smoothie` instead of type `Smoothie *`. The current code leaks memory. In other words, replace `Smoothie *juice = malloc(sizeof(Smoothie));` with `Smoothie juice;`, replace `juice->tab` with `juice.tab` and replace `return *juice;` with `return juice;`. – Ian Abbott Apr 03 '18 at 16:26
  • @Skyris - as Ian Abbott writes: If you use `Smoothie init(size_t n)` you have a memory leak as the function returns a copy and then the `juice` pointer is lost. If you actually want to return a `Smoothie`don't allocate it dynamic. Just use a local variable. – Support Ukraine Apr 03 '18 at 16:28
  • @4386427 Ok. Then how am I supposed to only use the local variable ? I don't get it (Sorry, I'm new to C) – Skyris Apr 03 '18 at 16:32
  • @Skyris `Smoothie* juice = malloc(sizeof(Smoothie));` -> `Smoothie juice;` and `return *juice;` -> `return juice;` – Support Ukraine Apr 03 '18 at 16:34
  • @4386427 Wait... Actually I have an idea. What if I do this: `Smoothie juice;` then `juice.tab = calloc(n,sizeof(fruit));` ? – Skyris Apr 03 '18 at 16:35
  • @Skyris - yep, that's it. Correct it shall be `juice.tab` instead of `juice->tab` – Support Ukraine Apr 03 '18 at 16:37
  • @4386427 Thank you, I get it. One more question though. Is it really a good idea to return the combination then ? Wouldn't it be better to return a pointer ? (I guess that's what you were telling me at first). Because, I will be creating a copy of it. Is that right ? – Skyris Apr 03 '18 at 16:40
  • 1
    @Skyris It's fine to return a struct. It is most likely less expensive than calling `malloc`. You return a pointer when you `malloc` an array of `Smoothie` but since you only have one, it's better just to return it. – Support Ukraine Apr 03 '18 at 16:46

1 Answers1

3

So, since I want to initialize all the values of my array to APPLE, is it very useful to use memset()?

No. memset() fills an area with a byte value. The size of an enum can vary, but it is normally an int, which is larger than a byte. You will fill your memory with something undefined. (Except of course for the enum member with the value 0)

How can I be sure that the compiler will understand that the values in my array are fruit variables and not just integers?

You already did that by declaring it of type fruit. But it doesn't help much, because the conversion between integer and enum value in C is implicit.


All in all, if you need to initialize memory to an enum value other than 0, you will need to write a loop. If you indeed want the value corresponding to 0, calloc() will do, it doesn't matter as 0 is still 0 :)

  • Just a question though. So let's say I don't use the `memset()`,and now that I have my array initialized at 0 everywhere, how do I make the compiler understand that each 0 is a `color` and not an `int` ? Do I have to do some kind of typecasting? – Skyris Apr 03 '18 at 16:38
  • 1
    An enum uses an integer type for representation and all bits 0 means `0` in any integer type, so it's just the same. –  Apr 03 '18 at 16:41