0

Hello I am experiencing something I really don't understand the principle with structures in C. One of my structures contains 2 character strings (named 'seq' and 'foldedSeq'). Both these strings (should) have the same dimensions. However when I try to modify one, the second automatically takes the same modifications at the same specified place of the string.

Here is the interesting chunk of code:

typedef struct MD {

 int nb_line;
 int nb_colomn;
 EM ** matrix; 
 char * seq;  // Initial sequence.
 char * foldedSeq;
} MD;


void set_sequences(MD * M, char * seq) {

 M->seq = seq;
 M->foldedSeq = M->seq; //Purpose: give to foldedSeq the seq dimensions (perhaps it is useless).


 printf("seq= %s\tstrlen= %d\nM->seq= %s\nM->foldedSeq= %s\n", seq, strlen(seq), M->seq, M->foldedSeq);
  // Up to this point 'seq' = 'foldedSeq'


 int i;
 for( i = 0; i < strlen(seq); i++) {
  M->foldedSeq[i] = '-'; // Original purpose: make 'foldedSeq' string filled with hyphens only.
 } 

 printf("seq= %s\tstrlen= %d\nM->seq= %s\nM->foldedSeq= %s\n", seq, strlen(seq), M->seq, M->foldedSeq);
// Here is the problem: the string 'seq' REALLY IS modified alongside with 'foldedSeq'... WHY? :(
}

Since I wrote "M->foldedSeq[i]" should be modified, why would "M->seq[i]" be modified as well ??

Thank you for reading and providing me explanations, my logic found a dead end here.

Alexandre Toqué
  • 173
  • 1
  • 3
  • 11

5 Answers5

2
 M->seq = seq;
 M->foldedSeq = M->seq;

is the same as saying

 M->seq = seq;
 M->foldedSeq = seq;

They are both pointing to the same location in memory. So modifying one is modifying both.

Probably what you want to do instead is malloc a block of memory that is the same length as the other.

 M->foldedSeq = calloc(strlen(seq) + 1, sizeof(char));
FDinoff
  • 30,689
  • 5
  • 75
  • 96
  • Aren't you missing a `strcpy` following the `malloc`? As it stands, the code delivers a suitably sized block of uninitialised memory. – simonc May 15 '13 at 14:32
  • @simonc The comment just say that it wants the same length not the same contents. And he immediately fills it with `-`. – FDinoff May 15 '13 at 14:33
  • What's `q`? Did you mean + 1 for the null termination? – Lundin May 15 '13 at 14:35
  • @FDinoff If you look at the code, there are a couple of `printf` lines which assume that `M->foldedSeq` is a nul-terminated string. These will have undefined results with your suggested change. – simonc May 15 '13 at 14:36
  • @Lundin q was a typo. Also every string in c ends with a null terminator. Which is not taken into accound by strlen. – FDinoff May 15 '13 at 14:38
  • Ah! Because 'seq' is the memory location of seq[0] right? Why didn't I find it myself :P Why would I chose a calloc instead of a malloc? "M->foldedSeq = malloc(strlen(seq) + 1 ); " works fine :) – Alexandre Toqué May 15 '13 at 14:47
  • @AlexandreToqué `calloc` zeroes all the memory. Where as malloc might return garbage. (and might not have a null terminator at the end of the string). – FDinoff May 15 '13 at 14:58
  • Well thanks to all of you on this page! I'll be more vigilant next time ;) – Alexandre Toqué May 15 '13 at 15:20
0

This line:

 M->foldedSeq = M->seq;

is setting the foldedSeq pointer to the same value as seq. It is not creating new space and copying the contents of seq to foldedSeq which is maybe where the confusion is. So when you modify either one the other will be modified as well. One possible solution is to use strdup:

M->foldedSeq = strdup( M->seq ) ;
Community
  • 1
  • 1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
0

What you're witnessing is simple pointer aliasing, a basic feature of the C language. Because you explicitly assign both seq and foldedSeq members to point to the same bit of memory, and modifications through one pointer will be witnessed by the other. If that's not what you intended/wanted, you'd need to copy the memory block of seq before assigning it to foldedSeq to keep the two distinct.

Scott Jones
  • 2,880
  • 13
  • 19
0

Because they both point to the same memory address and when you modify one you are modifying the other. This assignment: M->foldedSeq = M->seq; is just assigning memory locations, not doing any sort of copy. If you want to keep them separate, you will have to allocate memory and copy the string into the new memory.

edtheprogrammerguy
  • 5,957
  • 6
  • 28
  • 47
0

Try either: M->foldedSeq = strdp(M->seq) if you want to copy the content too.

Or:

M->foldedSeq = malloc(strlen(M->seq) + 1); to just have a new memory space of the same size.

yoones
  • 2,394
  • 1
  • 16
  • 20