38

A structure type is defined as:

typedef struct student{
    int id;
    char* name;
    double score;
} Student;

I construct a variable of type Student and I want to assign values to it. How can I do that efficiently?

int main(){
    Student s1;

    int id = 3;

    char* name = getName(id);

    double score = getScore(id);

    /*Error
    s1 = {id, name, score};
    */

    /*  Can I avoid assigning values individually?
    s1->id = id;
    s1->name = name;
    s1->score= score;
    */

    return 0;
}
Alex Marchant
  • 2,490
  • 27
  • 49
Frankie
  • 433
  • 1
  • 6
  • 6
  • 3
    Unless I did not understand the question, this is a "C Basic learning" question which should be answered by itself by simply learning what C structs are and how to use them. Yet you are talking about accessing a struct instance using a unique ID. Then you should also see what "C pointers" are for that one. – Oragon Efreet Sep 23 '15 at 16:11

3 Answers3

136

In C99 standard you can assign values using compound literals:

Student s1;
s1 = (Student){.id = id, .name = name, .score = score};
Alexander Ushakov
  • 5,139
  • 3
  • 27
  • 50
  • 44
    I can't believe nobody gives this answer until May 10, 2017. – Nick Lee May 17 '17 at 14:06
  • 1
    So what happens if you don't specify all the parameters? For instance, say s1 is already initialized and you want to override name and score, but not id. Can you just say `s1 = (Student) {.name = name, .score = score}`? Or would that overwrite id in some way? And is that behavior portable? – gabe appleton Oct 13 '19 at 00:44
  • 7
    @gabeappleton Struct assignment always replace left side struct with the data from right side. On the right side of your sample is structure with designated initializer which missing fields will be initialized to zero by default. And then s1 will be replaced with content of new structure. So id field will be set to zero. – Alexander Ushakov Oct 13 '19 at 06:28
  • For more information see https://stackoverflow.com/questions/24936022/designated-initializers-and-compound-literals-for-struct-in-c – Alexander Ushakov Oct 13 '19 at 06:36
  • Just to spare you some googling: The keyword is "compound literals" - see e.g. https://en.cppreference.com/w/c/language/compound_literal. – jerico Nov 11 '20 at 06:30
  • I believe you do not need the individual assignment for each value: s1 = (Student) {id, name, score} (see link by jerico) – BobtheMagicMoose Nov 24 '20 at 18:07
  • 1
    @BobtheMagicMoose "individual assignment" here is `designated initializers`. It is another type of initializer than `value initializer` in your example. Using designated initializers we can omit values for some fields. And such initializer allows to distinguish struct init from array init which are similar in case of value initializer. In @jerico link there are designated initializers in examples for structs too. – Alexander Ushakov Nov 24 '20 at 19:53
  • 1
    You can use any initializer type as you wish. C standard allows both of them. – Alexander Ushakov Nov 24 '20 at 19:54
40

Beware, struct and pointer to struct are 2 different things.

C offers you:

  • struct initialization (only at declaration time):

    struct Student s1 = {1, "foo", 2.0 }, s2;
    
  • struct copy:

    struct Student s1 = {1, "foo", 2.0 }, s2;
    s2 = s1;
    
  • direct element access:

    struct Student s1 ;
    s1.id = 3;
    s1.name = "bar";
    s1.score = 3.0;
    
  • manipulation through pointer:

    struct Student s1 = {1, "foo", 2.0 }, s2, *ps3;
    ps3 = &s2;
    ps3->id = 3;
    ps3->name = "bar";
    ps3->score = 3.0;
    
  • initialization function:

    void initStudent(struct Student *st, int id, char *name, double score) {
        st->id = id;
        st->name = name;
        st->score = score;
    }
    ...
    int main() {
        ...
        struct Student s1;
        iniStudent(&s1, 1, "foo", 2.0);
        ...
    }
    

Pick among those (or other respecting C standard), but s1 = {id, name, score}; is nothing but a syntax error ;-)

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
7

Can I avoid assigning values individually?

You can if the values are already part of a similar struct, that is, you can do this:

Student s1 = {.id = id, .name = name, .score = score};

which creates an instance of Student and initializes the fields you specify. This probably isn't really any more efficient than assigning values individually, but it does keep the code concise. And once you have an existing Student instance, you can copy it with simple assignment:

Student s2;
s2 = s1;    // copies the contents of s1 into s2

If the values are all in separate variables and you're not initializing the Student, then you'll probably need to assign the values individually. You can always write a function that does that for you, though, so that you have something like:

setupStudent(s3, id, name, score);

That'll keep your code short, ensure that the struct is populated the same way every time, and simplify your life when (not if) the definition of Student changes.

Caleb
  • 124,013
  • 19
  • 183
  • 272