admin管理员组

文章数量:1319472

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

void f(char s1[], const char s2[], int i, int j) {
    if (i >= 0 && j >= 0) {
        s1[i] = s2[j];
        f(s1, s2, i + 1, j - 1);
    }
}

int main() {
    char s1[5] = {'\0'}, s2[] = "hello";
    f(s1, s2, 0, (int)strlen(s2) - 1);
    printf(" %s \n", s1);
    return 0;
}

Hello, The print of this code is olleh but I expected the code to give an error as the null character was overwritten during the for loop, why this happen?

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

void f(char s1[], const char s2[], int i, int j) {
    if (i >= 0 && j >= 0) {
        s1[i] = s2[j];
        f(s1, s2, i + 1, j - 1);
    }
}

int main() {
    char s1[5] = {'\0'}, s2[] = "hello";
    f(s1, s2, 0, (int)strlen(s2) - 1);
    printf(" %s \n", s1);
    return 0;
}

Hello, The print of this code is olleh but I expected the code to give an error as the null character was overwritten during the for loop, why this happen?

Share Improve this question asked Jan 19 at 19:27 Tommaso AnsaloniTommaso Ansaloni 91 silver badge1 bronze badge 6
  • All characters in s1 start out as "the null character", and you overwrite all of them. What you need to remember is that s2 is an array of six characters, and you need to make s1 at least the same size. – Some programmer dude Commented Jan 19 at 19:35
  • Also, the condition i >= 0 will always be true, as it starts out as 0 and then only get increased in the recursive calls. – Some programmer dude Commented Jan 19 at 19:36
  • And please make it a habit to give good names to your functions and variables. At a quick glance it's very hard to know what the function f is doing, and what the argument variables i and j represent. Comments could also help. For example, I would probably name f as copy_reverse or something similar, and s1 would be dest, s2 would be source, and i and j would then be dest_pos and source_pos (respectively). – Some programmer dude Commented Jan 19 at 19:38
  • 2 At the end of the recursions s1 is {'o', 'l', 'l', 'e', 'h'} (all 5 bytes of the array). It's an error (it's UB) to use that in printf() with "%s" because no '\0' is present; or, in other words, because s1 is NOT a string. One of the possible manifestations of UB is behaving like expected (the most annoying UB and most difficult to diagnose and correct). – pmg Commented Jan 19 at 19:43
  • Did you expect the compiler to give an error message or did you expect some kind of error message when running the code? – nielsen Commented Jan 20 at 8:16
 |  Show 1 more comment

2 Answers 2

Reset to default 4

If you try to print using %s and pass a non-null-terminated string, it will invoke undefined behavior.

However, in your case, char s1[5] = {'\0'} fills the entire array with zeroes. Therefore, if strlen(s2) < sizeof(s1) (s1 and s2 in the main function scope), this code will work correctly.

If strlen(s2) >= sizeof(s1), it will invoke undefined behavior because:

  • You will write outside the array bounds if strlen(s2) > sizeof(s1).
  • You will pass a non-null-terminated string to printf if strlen(s2) >= sizeof(s1).

The print of this code is olleh, but I expected the code to give an error since the null character was overwritten during the for loop. Why does this happen?

Overwriting the first character does not matter because your array is zeroed out when initialized as you did. The issue arises because there is no space for a null-terminating character if the conditions I explained above are met. This invokes undefined behavior. Undefined behavior does not have to manifest in a specific way—the code might work fine, cause a segmentation fault, transfer all your money, or do something else entirely.

In your case, it is likely that there was a zero in the next byte past the end of the s1 array.

… I expected the code to give an error…

It is incorrect to expect this. When printf is passed, for a %s conversion, an array that does not contain a null character, then the behavior is not defined by the C standard.

Nothing specifies that the computer will give an error. There is no specification from the C standard about what the behavior will be.

Often, what will happen is that printf will continue examining memory beyond the end of the array and printing what it finds until a zero byte is found. There might have been a zero byte immediately after your s1 array, so printf stopped right away. However, other behaviors are possible. printf might have printed additional characters that you did not see because they had no visible effect, like spaces or tabs or certain control characters. In other situations, there might be other characters beyond your array, and printf might print those. Or, during optimization, the compiler might have transformed your program in ways that produce other effects.

本文标签: cUnexpected null character behaviour when inserting into an arrayStack Overflow