-1

I have this struct

struct FluxCapacitor{
    unsigned char* c_string;
    unsigned int value;
};

Now I need to create an instance of this struct. I googled this problem and found that I have to use something like this

typedef struct FluxCapacitor{
    unsigned char* c_string
    unsigned int value;
};  

But I dont really understand the next step with malloc(). Can someone explain it to me?

dtell
  • 2,488
  • 1
  • 14
  • 29
Timm
  • 1
  • 2
  • 3
  • 1
    You mean 'malloc', you're going to have to do some research of your own. – Jack Gore Apr 03 '17 at 17:59
  • oh yes I mean malloc I miss spelled it sorry – Timm Apr 03 '17 at 18:00
  • 1
    What you need is a basic C tutorial. Also you don't always need to use `malloc` to allocate `struct`s – UnholySheep Apr 03 '17 at 18:02
  • 1
    Possible duplicate of [How to create a new instance of a struct in C](http://stackoverflow.com/questions/32577808/how-to-create-a-new-instance-of-a-struct-in-c) – Gaurav Pathak Apr 03 '17 at 18:03
  • Yes I saw this question too but as I said I did not get the part with malloc. So I thought someone could explain it to me. I am not asking for a solution for my problem I am just asking for someone to explain me the malloc part – Timm Apr 03 '17 at 18:09
  • `typedef` at the beginning of that struct definition is useless. – aschepler Apr 04 '17 at 01:06

2 Answers2

1

You do not need malloc() to create an instance of a struct. And I would recommend that you avoid typedefing structures merely to reduce keystrokes. The extra keystrokes would only be saved in declarations and function prototypes (and maybe if you need to cast something), since you don't need the struct keyword elsewhere; the advantage is that when you see struct FluxCapacitor, you know exactly what it is. If you only see FluxCapacitor alone, you don't know if it is a typedef for a struct, or a union, or an integer type or what.

Note that the posted code was missing the semicolon at the end of the declaration. Also, it is unclear why you have unsigned char* c_string;. This may not allow assignment to a string literal. I have changed this in the code below. You can create a single struct like this:

struct FluxCapacitor
{
    char *c_string;
    unsigned int value;
};

...

struct FluxCapacitor fcap_1;

You can then assign values to the fields of fcap_1:

fcap_1.c_string = "McFly";
fcap_1.value = 42;

Note that you could also use designated initializers at the point of declaration:

struct FluxCapacitor fcap_2 = { .c_string = "Biff",
                                .value = 1985
};

If you need an array of FluxCapacitor structures, just declare one:

struct FluxCapacitor fcaps[2];

You can assign to the fields of each array member in a loop:

struct FluxCapacitor fcaps[2];

char *somestrings[] = { "McFly", "Biff" };
unsigned somevalues[] = { 42, 1985 };

for (size_t i = 0; i < 2; i++) {
    fcaps[i].c_string = somestrings[i];
    fcaps[i].value = somevalues[i];
}

Alternatively, you can use designated initializers here too:

struct FluxCapacitor fcaps[2] = { { .c_string = "McFly", .value = 42 },
                                  { .c_string = "Biff", .value = 1985}
};

Using malloc()

Since OP seems determined to use malloc(), it would be good to first recall that memory allocated with malloc() must later be deallocated with free(). Also note that malloc() can fail to allocate memory, returning a null pointer. Thus the result of a call to malloc() must be checked before attempting to dereference this pointer. The additional complexity should be avoided in favor of the above approaches unless OP has good reason to do manual allocation.

In the code below, the function create_flux_cap() takes a string and an unsigned int as arguments, and returns a pointer to a newly allocated FluxCapacitor structure with the arguments assigned to the appropriate fields. Note that since the FluxCapacitor structure is accessed through a pointer, the arrow operator is used instead of the dot operator.

Inside the function, the return value from the call to malloc() is checked before attempting assignment. If the allocation has failed, no assignment is made and a null pointer is returned to the calling function. Note that in the call to malloc(), the result is not cast, since there is no need for this in C and it needlessly clutters the code. Also observe that an identifier is used instead of an explicit type with the sizeof operator. This is less error-prone, easier to maintain if types change in the future, and is much cleaner code. That is, instead of this:

new_fcap = (struct FluxCapacitor *)malloc(sizeof (struct FluxCapacitor));

use this:

new_fcap = malloc(sizeof *new_fcap);

In main(), the return values from the calls to create_flux_cap() are checked. If an allocation has failed, the program exits with an error message.

The stdlib.h header file has been included for the function prototypes of malloc() and exit(), and also for the macro EXIT_FAILURE.

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

struct FluxCapacitor
{
    char* c_string;
    unsigned value;
};

struct FluxCapacitor * create_flux_cap(char *, unsigned);

int main(void)
{
    struct FluxCapacitor *fcap_1 = create_flux_cap("McFly", 42);
    struct FluxCapacitor *fcap_2 = create_flux_cap("Biff", 1985);

    /* Check for allocation errors */
    if (fcap_1 == NULL || fcap_2 == NULL) {
        fprintf(stderr, "Unable to create FluxCapacitor\n");
        exit(EXIT_FAILURE);
    }

    /* Display contents of structures */
    printf("%s, %u\n", fcap_1->c_string, fcap_1->value);
    printf("%s, %u\n", fcap_2->c_string, fcap_2->value);

    /* Free allocated memory */
    free(fcap_1);
    free(fcap_2);

    return 0;
}

struct FluxCapacitor * create_flux_cap(char *str, unsigned val)
{
    struct FluxCapacitor *new_fcap;

    new_fcap = malloc(sizeof *new_fcap);

    if (new_fcap != NULL) {
        new_fcap->c_string = str;
        new_fcap->value = val;
    }

    return new_fcap;
}
ad absurdum
  • 19,498
  • 5
  • 37
  • 60
-2

You need malloc for dynamic allocation of memory.In your case, both the types char and int are known to the compiler, it means the compiler can know the exact memory requirement at compile time.

For e.g. you can create a struct object like in the main function

 #include<stdio.h>
 #include<stdlib.h>
 struct FluxCapacitor{
    unsigned char* c_string;
    unsigned int value;
 };

 int main() {
     FluxCapacitor x;
     x.c_string = "This is x capacitor"
     x.value = 10
 }

The x is of value type. You can make a copy and pass around this value. Also, observe we are using . notation to access its member variables.

But this doesn't happen at all time. We are not aware of future FluxCapacitor requirement and so above program will need more memory as while it is running and by using the malloc we can ask the compiler to provide us requested memory. This is a good place to use malloc, what malloc does is, it returns us a pointer to a piece of memory of the requested size. It is dynamic memory allocation.

Here's a simple example: let suppose if you need struct declaration of FluxCapacitor but don't know how many you will need, then use malloc

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

typedef struct FluxCapacitor {
   unsigned char* c_string;
   int value;;
} flux;
// typedef is used to have the alias for the struct FluxCapacitor as flux

int main() {
    flux *a = malloc(sizeof(flux)); // piece of memory requested
    a -> c_string = "Hello World";  // Pointer notation
    a -> value = 5;

    free(a);                       // you need to handle freeing of memory
    return 0;
}

.

Rahul
  • 2,056
  • 1
  • 21
  • 37
  • Well I think I understand. In my example I have to use your second case beacuse my types aren´t primitive. – Timm Apr 03 '17 at 18:32
  • Then you will have to use `malloc`. malloc(sizeof(FluxCapacitor) ); – Rahul Apr 03 '17 at 18:52
  • Yes but is my part correct with the typedef? I talked to a friend of me and he said no you dont have to use typedef. I mean there are probably more ways to create an instance of a struct. Is my instance correct? – Timm Apr 03 '17 at 19:12
  • `typedef ` is giving your type a custom name. `typedef struct FluxCapacitor {} flux`. It means now I can refer `struct FluxCapacitor` with `flux`. – Rahul Apr 03 '17 at 19:17
  • So I can basically rename my struct. Then is this code part I wrote with typedef pretty useless because its not an instance that I want create from the struct am I right? – Timm Apr 03 '17 at 19:28
  • 1
    This is wrong. Having pointers of any sort in your struct does not force you to use `malloc`. – aschepler Apr 04 '17 at 01:40
  • @DavidBowling I have given the second example with `*next` pointer to show when `malloc` would be required. First example is explained as asked in the question. – Rahul Apr 04 '17 at 15:02
  • Ok, I will update the answer. I tried to explain the second example in linklist term but I think I was not clear enough. – Rahul Apr 04 '17 at 15:25