-1

Hi i have a struct array which has a char * property. However, when i try to assign multiple values to each element, when i go to read only the last value that i have written shows in all of the elements. Somehow, all char* properties have the same memory adress.

#include <stdio.h>
#include <string.h>

struct Identity{
    char *name;
    int idNumber;
} identities[5];

int main(){

    int i;
    char tempName[20];

    for(i = 0; i < 2; i++){
        printf("IDENTITY %d\n", i+1);
        printf("Name: ");
        fgets(tempName, 20, stdin);
        strtok(tempName, "\n");
        identities[i].name = tempName;
        printf("Id: ");
        scanf("%d", &identities[i].idNumber);
        getchar();
    }

    for(int i = 0; i < 5; i++){
        printf("MEMORY %d: %ld\n", i+1, identities[i].name); // FILLED VALUES HAVE EQUAL MEMORY ADRESS???? WHY??
    }



    printf("***OUTPUT***\n");

    for(i = 0; i < 5; i++){
        printf("IDENTITY %d\n", i+1);
        printf("Name: %s\n", identities[i].name);
        printf("Id: %d", identities[i].idNumber);
        if(i != 4){
            printf("\n");
        }
    }



    return 0;
}

  • 1
    You assign `tempName` to all of them so they all point to `tempName`. Why should they point to something different? – Blaze Sep 10 '19 at 08:45
  • Because you read the strings into a temporary buffer on the stack and then save the pointer to that buffer in your structure. This then gets overwritten the next time you use the buffer. You'll need to allocate memory for a copy of the string and save the copy in the structure, e.g. with strdup. – Rup Sep 10 '19 at 08:46
  • So this is happening because in spite the value of tempName changes over the curse of the loop, the pointer is always the same. So since i´m assigning char * name to be equal to that pointer in every single element, the value results to be the last value inserted into tempName in the loop, right? – João Marques Sep 10 '19 at 09:03

1 Answers1

2

This line is the problem:

identities[i].name = tempName

Here you make all structures name member point to the first element of tempName.

I suggest you make the name member an array, and copy the string into it instead.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • I´m not understanding how can that be if im writing only to one element of the struct array -> identities[i] . Thanks for your reply – João Marques Sep 10 '19 at 08:51
  • @JoãoMarques If you *unroll* your loop you basically do `identities[0].name = tempName;` and then `identities[1].name = tempName;`... And remember that assignment to a pointer only assigns the pointer, it doesn't create a new copy of a string. – Some programmer dude Sep 10 '19 at 08:57
  • @JoãoMarques The assignment `identities[i].name = tempName;` does not copy the string (the characters), it only copies the address of the memory where the string is stored. You use the same memory in every cycle of your loop, so all structures contain the same address and the memory contains the last string only. As mentioned in Rup's comment, you could use `identities[i].name = strdup(tempName);` to allocate memory and create a copy of the string. You should then use `free(identities[i].name)` when you no longer need the memory. – Bodo Sep 10 '19 at 08:57