1

Initial I didn't intend to go deeper of this example, coz I think it's just several lines, not big deal, but when I use the hello world to test and verify my thought, I find something quite abnormal! here is the code part without too much comments:

#include<stdio.h>
void concatenate(char s[], char c[]);
int main(){
    char s[] = "hello";
    char c[] = "world";
    concatenate(s, c);
    printf("%s\n",s);
    return 0;
}
void concatenate(char s[], char c[]){
    int i, j;
    i = j = 0;
    while(s[i] != '\0')/* find the end of s*/
        i++;
    while((s[i++] = c[j++]) != '\0') /* copy c string */
        printf("%d,%c\n", i, s[i]);
    printf("0,%c\n", s[0]);
    printf("1,%c\n", s[1]);
    printf("2,%c\n", s[2]);
    printf("3,%c\n", s[3]);
    printf("4,%c\n", s[4]);
    printf("5,%c\n", s[5]);
    printf("6,%c\n", s[6]);
    printf("7,%c\n", s[7]);
    printf("8,%c\n", s[8]);
    printf("9,%c\n", s[9]);
    printf("10,%c\n", s[10]);
}

how to run it? I'm using ubuntu 64-bit 18.04 version===> cc concat.c the output:

enter image description here

enter image description here From the screenshot, it is so hard to imagine why the output is like this, could anyone plz spend a bit of time explaining why it is this?? really appreciate it!

Thomas
  • 107
  • 1
  • 10
  • 4
    `char s[] = "hello"` -> `char s[100] = "hello";`. Otherwise there is only space for 5 characters (length of "hello") in `s`. – Jabberwocky Mar 11 '21 at 14:24
  • 1
    Also `printf("%d,%c\n", i, s[i]);` -> `printf("%d,%c\n", i, s[i - 1]);`, otherwise you're not printing the character you just copied but something else – Jabberwocky Mar 11 '21 at 14:27
  • @Jabberwocky, thx for your help, in this example, what I want to do is, in the copy string part, say, I is 5, then after copying the character I will be 6, which is the true value, it is also true that s[5] is w, but why s[6] is also w, which the point that should be figured out, by the way, instead of printf("%d,%c\n", i, s[i]); it should be printf("%d,%c\n", i-1, s[i-1]); both i should decrement by 1 – Thomas Mar 11 '21 at 14:38
  • You're reading and writing past the end of the `s` array, which results in _undefined behaviour_ (google that term). – Jabberwocky Mar 11 '21 at 14:46
  • @Jabberwocky, Yes I google that, well, from this stackoverflow question,[link](https://stackoverflow.com/questions/50083744/how-to-create-an-array-without-declaring-the-size-in-c), it is pretty ok to define character array without size initialized, So it is not wrong, so if it results in undefined behavior, it is still showing world, is that coincidence?? – Thomas Mar 11 '21 at 14:57
  • 1
    It is ok to define an array without size initialized , like `char foo[] = "Bar"`, but it not OK to read/write beyond the end of an array. With `char foo[] = "Bar"`, the size of the `foo` array is 4, so accessing `foo[4]` is wrong and results in undefined behaviour. – Jabberwocky Mar 11 '21 at 15:00
  • @Jabberwocky, maybe I know the reason now, I edit my question again, I upload a new image directly from the book, it says s should be large enough, I change to 100, then on the first 5 lines which is where 6,7,8,9,10 are, do not output characters, which is reasonable coz, it does NOT have value yet, the real reason I think maybe s and c array sit next to each other on the memory so by accident, it output the same value, this is just my guess, thx for your time! – Thomas Mar 11 '21 at 15:18
  • _"I think maybe s and c array sit next to each other on the memory so by accident..."_: that's most likely the cause. – Jabberwocky Mar 11 '21 at 15:19

1 Answers1

0

On one hand, there is something wrong in here:

Due to the post-increment of i, you should use:

  while((s[i++] = c[j++]) != '\0') /* copy c string */
        printf("%d,%c\n", i, s[i-1]);

instead of s[i] , otherwise you would print garbage values like this:

6,(
7, 
8,(
9,
10,4
0,h
1,e
2,l
3,l
4,o
5,w
6,o
7,r
8,l
9,d
10,

on the other hand, you are affecting c[j++] to s[i++], thus copying the text 'hello' from c to s from index iwhich is 5 to the index 10. This allows for copying the content of c[] to s[] from the end of hello, making it containing helloworld\0.

A good reference, for a first thought can be to look at iso/iec doc section 6.7.8 example 8 (page 130).

It is stated that :

The contents of the arrays are modifiable

Pat. ANDRIA
  • 2,330
  • 1
  • 13
  • 27
  • thx for your answer, if I do change to `while((s[i++] = c[j++]) != '\0') /* copy c string */ printf("%d,%c\n", i, s[i-1]);` for s[i-1] it will output the expected result,, not garbage value at all, so I don't think that's the reason – Thomas Mar 11 '21 at 15:01
  • I meant that your original code was `printf("%d,%c\n", i, s[i]);` which is wrong imho. – Pat. ANDRIA Mar 11 '21 at 15:02
  • haha, yeah `printf("%d,%c\n", i, s[i]); ` it 's wrong, coz s[i] should be undefined, but the result is still world!!!!! how come?? – Thomas Mar 11 '21 at 15:08
  • @Thomas undefined behaviour is undefined. If you want to know what exactly is happening when you read/write beyond the end of the array, then you need to analyse your compiler's assembly output. – Jabberwocky Mar 11 '21 at 15:18
  • @Jabberwocky, thanks for your advice, well, after this book's reading and exercises, I will start CSAPP book, I think that's the time to study some assembly code – Thomas Mar 11 '21 at 15:20