简体   繁体   中英

C Programming - Structs, Pointers, and Initialization

I'm still fairly new to programming in C, and still learning the language. I'm trying to do the following (its a scaled down version of my initial program code). But every time I try to initialize counter , the program crashes. I've tried setting up another function to handle the initialization process, setting up the counter to be incremented in the set_members function, and tried initializing the counter by passing it the address of total &total . But every time I try to run my program, it crashes after printing "Hello" . I think I'm trying to initialize counter incorrectly because I don't fully understand pointers and structs in C. Can someone explain how or why my initialization process is incorrect, and causes my program to crash? And how I can do it correctly going forward? Thanks!

typedef struct CharStruct{
    char *names;
}CharStruct;

typedef struct Count{
    CharStruct *arr;
    int counter;
}Count;

typedef struct Members{
    Count *member;
}Members;

typedef struct Test{
    Members people;
}Test;

void set_members(struct Test *person);
void print_total(struct Test *person);

int main(void) {
    printf("Hello\n"); /* prints Hello */
    Test person;
    //person.people.member->counter = 0;
    set_members(&person);
    print_total(&person);
    system("pause");
    return EXIT_SUCCESS;
}

void set_members(struct Test *person)
{
    int total = 0;

    while(total < 10)
    {
        ++total;
    }
    person->people.member->counter = total;
}


void print_total(struct Test *person)
{
    printf("Total Members: %d\n", person->people.member->counter);
}

When you take a look at the:

typedef struct Members{
    Count *member;
}Members;

please notice that member is a pointer pointing to the Count type object. To be able to operate on that object the object has to exist. Memory for it has to be dynamically or statically allocated. Otherwise, the behavior of your program in undefined.

Check the memory allocation done in the sample program:

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

typedef struct CharStruct{
    char *names;
}CharStruct;

typedef struct Count{
    CharStruct *arr;
    int counter;
}Count;

typedef struct Members{
    Count *member;
}Members;

typedef struct Test{
    Members people;
}Test;

void set_members(struct Test *person)
{
    int total = 0;
    while(total < 10){
        ++total;
    }
    person->people.member->counter = total;
}

void print_total(struct Test *person)
{
    printf("Total Members: %d\n", person->people.member->counter);
}

int main(void) {
    printf("Hello!\n"); /* prints Hello */ 
    Test person;     
#if 0 // allocate memory on stack
    Members m;
    Count   c;
    // use declared variables 
    person.people = m;  
    m.member = &c; 
#else    
    // or dynamic alocation
    person.people.member = malloc(sizeof(Count)); 
#endif

    set_members(&person);
    print_total(&person);

    person.people.member->counter = 77;
    print_total(&person);

    free(person.people.member);

    //system("pause");
    return EXIT_SUCCESS;
}

Output:

Hello!                                                                                                                                     
Total Members: 10                                                                                                                          
Total Members: 77

The memory for object of type Count where type Count

typedef struct Count{
    CharStruct *arr;
    int counter;
}Count;

was allocated by:

malloc(sizeof(Count));

It is worth to stress that you can use the int counter but CharStruct *arr points to undefined memory location.

Again, to safely use member arr it has to point to a valid object of type CharStruct . You should allocate memory for the CharStruct . That is not all. Once you have object CharStruct it has char *names pointer for pointing to the string. If you want to use names it should point to the valid string!

Your chain of nested structures with pointers will require very careful memory handling for allocation and deallocation. Be aware of potential memory leaks or uninitialized pointers. Those are one of the most common problems encountered by many C programmers.

person.people.member is a pointer which is not initialized. It has some garbage value which might be the address of some memory location that the program is not allowed to access.

As others have said, dereferencing an uninitialised pointer invokes undefined behavior.

You need to allocate memory for a struct Count and assign its address to person.people.member before writing value to it.

You could do

person.people.member = malloc(sizeof(struct Count));

in main() right after declaring person or do

person->people.member = malloc(sizeof(struct Count));

in set_members() before the person->people.member->counter = total; .

And don't forget to deallocate the memory once you are done using it like

free(person->people.member);

The same thing goes for the other pointers person.people.member->arr and person.people.member->arr->names .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM