30

What is the correct way to create a new instance of a struct? Given the struct:

struct listitem {
    int val;
    char * def;
    struct listitem * next;
};

I've seen two ways..

The first way (xCode says this is redefining the struct and wrong):

struct listitem* newItem = malloc(sizeof(struct listitem));

The second way:

listitem* newItem = malloc(sizeof(listitem));

Alternatively, is there another way?

Neuron
  • 5,141
  • 5
  • 38
  • 59
Robin Huang
  • 383
  • 2
  • 4
  • 6
  • 5
    *"(xCode says this is redefining the struct and wrong)"*. There's something you're not telling us, since the first way is neither redefining the struct nor wrong. – user3386109 Sep 15 '15 at 04:46
  • @user3386109 oh you're right! XCode only said it's wrong because I was using it in a function, not main(). Not sure why though... – Robin Huang Sep 15 '15 at 06:15

4 Answers4

33

It depends if you want a pointer or not.

It's better to call your structure like this :

typedef struct s_data 
{
    int a;
    char *b;
    // etc..
} t_data;

After to instanciate it for a no-pointer structure :

t_data my_struct;
my_struct.a = 8;

And if you want a pointer you need to malloc it like that :

t_data *my_struct;
my_struct = malloc(sizeof(t_data));
my_struct->a = 8

I hope this answers your question.

wasmup
  • 14,541
  • 6
  • 42
  • 58
Prog_is_life
  • 754
  • 1
  • 5
  • 15
21

The second way only works if you used

typedef struct listitem listitem;

before any declaration of a variable with type listitem. You can also just statically allocate the structure rather than dynamically allocating it:

struct listitem newItem;

The way you've demonstrated is like doing the following for every int you want to create:

int *myInt = malloc(sizeof(int));
  • The simple convention to always: ``typedef Foo_tag { ... } Foo_t`` and using the ``Foo_t`` forthwith works pretty well in C programming. There is really only the typing cost for the ``typedef`` but afterwards it ammortizes by never having to type ``struct Foo_tag`` at all. – BitTickler Sep 15 '15 at 04:45
  • `struct listitem newItem;` is only static allocation if it occurs at file scope. At block scope this is automatic allocation. – M.M Sep 15 '15 at 04:53
  • @M.M You're correct of course, but in general terms, `malloc` and friends deal with dynamic allocation while other forms of allocation, regardless of placement within a file, is frequently referred to as "static allocation" to differentiate it from dynamic allocation. –  Sep 15 '15 at 05:11
  • @BitTickler Personally I don't care either way. I will note that `typedef struct List_tag List; struct List_tag { List *next, *prev; int data };` works even better for structures requiring pointers to items of the structure type being defined. –  Sep 15 '15 at 05:15
  • @ChronoKitsune That is about the only time I ever use the ``struct tag_name``. When the structure needs pointers to self. ``typedef struct List_tag { struct List_tag *next;... } List_t;`` – BitTickler Sep 15 '15 at 05:17
  • 3
    Please note that names ending in `_t` are reserved for the implementation and should be avoided. See http://stackoverflow.com/a/12727104/1701799. – RastaJedi Aug 23 '16 at 18:43
5

Besides the other answers I'd like to add two more compact ways of creating instances. Example:

struct Person{
    float position[2];
    int age;
    char name[20];
}
struct Person p1 = { {4, 1.1}, 20, "John" };
struct Person p2 = { .age=60, .name="Jane", .position={0, 0} };
printf("%s, aged %i, is located at (%f, %f)\n", p1.name, p1.age,p1.position[0], p1.position[1] );
printf("%s, aged %i, is located at (%f, %f)\n", p2.name, p2.age,p2.position[0], p2.position[1] );

output:

John, aged 20, is located at (4.000000, 1.100000)
Jane, aged 60, is located at (0.000000, 0.000000)

Note that for p1 the order of properties matches that of the struct definition. If you don't want to type struct all the time when you use a type you can define a new alias using

typedef struct Person SomeNewAlias;
SomeNewAlias p1;

and you can call the new alias the same as the old namejust fine

typedef struct Person Person;
Person p1;
4
struct listitem newItem; // Automatic allocation
newItem.val = 5;

Here's a quick rundown on structs: http://www.cs.usfca.edu/~wolber/SoftwareDev/C/CStructs.htm

Scott G.
  • 323
  • 1
  • 10