C string at the end of ''
C string at the end of ''
While writing c code, I tried to write strcpy
code of my own, and I faced this issue.
strcpy
#include <stdio.h>
#include <string.h>
void strcpy2(char *s, char *t);
int main()
char a[10] = "asds";
char b[10] = "1234567890";
strcpy2(a, b);
printf("Copy completed! : %s", a);
return 0;
void strcpy2(char *s, char *t)
while ((*s++ = *t++));
Error code : Process finished with exit code -1073741819 (0xC0000005)
Thanks to this question on the s.o, I learned string should ends with '', but why the above code doesn't work even though it does not cause error when it is declared? (It worked well when char b[10] = "123456789")
So, How exactly '' affects this process and eventually cause the error? (Runtime? Compile time? etc)
(I only know '' should be the end of the string)
b
array is shorter with 1 byte to hold ''
. Make it char b[11]
.– i486
Sep 18 '18 at 11:25
b
''
char b[11]
Your
s
and t
names are highly misleading. Please reconsider. The image you have posted is totally irrelevant. You should not post any images of code or error messages, see here.– n.m.
Sep 18 '18 at 11:30
s
t
"How exactly '' affects this process?" - you move at runtime over the *t memory searching for 0 and because there is no 0, go over the allowed region and cause access violation. Step by step instruction: medium.com/@larissafeng/understanding-while-s-t-abb2cc518f96
– Alexey Voytenko
Sep 18 '18 at 11:37
I must apologise about the
s, t
thing. It's not wrong per se. Lots of people write strcpy
-like functions with *s=*t` or equivalent, inkluding K&R. It just drives me nuts. People, s
is supposed to stand for "source" and t
for "target"! If you must have one-letter variable names, and you must have the letters in alphabetical order, use p, q
or something! Better yet, use more sensible names like dst
and src
, or longer.– n.m.
Sep 18 '18 at 14:46
s, t
strcpy
s
t
p, q
dst
src
2 Answers
2
On the line char b[10] = "1234567890";
, the string literal "1234567890"
is exactly 10 characters + 1 null terminator. There is no room left in the array, so it doesn't get null terminated.
char b[10] = "1234567890";
"1234567890"
Normally, the compiler would warn you for providing an initializer which is too large, but this specific case is a very special pitfall. In the C standard's rules for initialization, we find this little evil rule (C17 6.7.9 §14, emphasis mine):
An array of character type may be initialized by a character string literal or UTF−8 string
literal, optionally enclosed in braces. Successive bytes of the string literal (including the
terminating null character if there is room or if the array is of unknown size) initialize the
elements of the array.
There is no room in your case, so you don't get a null character. And because of this weird little rule, the compiler doesn't warn against it either, because the code conforms to the C standard.
@Bathsheba Oh. Thanks, I had forgotten about this whole rep thing! :) As for this particular quirk, I actually didn't know about it myself until some years ago when I learnt it from SO here.
– Lundin
Sep 18 '18 at 11:32
@Lundin I have a problem. I compile OPs code with:
-Wpedantic -std=c17 -Wall -Wextra -Werror -Wstrict-prototypes -Wmissing-prototypes -Wmisleading-indentation -Wduplicated-cond -Wold-style-definition -Wconversion -Wshadow -Winit-self -Wfloat-equal -Wwrite-strings -Wcast-align=strict -O0 -g -Wformat
and valgrind Does not catch this problem. Even with O0, O1, O2 and O3
Why? This is the Output from valgrind. I useGCC-8.0.1
– Michi
Sep 18 '18 at 11:36
-Wpedantic -std=c17 -Wall -Wextra -Werror -Wstrict-prototypes -Wmissing-prototypes -Wmisleading-indentation -Wduplicated-cond -Wold-style-definition -Wconversion -Wshadow -Winit-self -Wfloat-equal -Wwrite-strings -Wcast-align=strict -O0 -g -Wformat
O0, O1, O2 and O3
GCC-8.0.1
Wow you are god of C! It helped a lot
– ProbieH
Sep 18 '18 at 11:38
@Michi Because as I said, the code conforms to the C standard, so gcc doesn't give an error on purpose. Neither does clang or icc, just tested with max warnings (various embedded systems compilers do, however). I don't believe a C++ compiler would allow it though, g++ gives an error. Valgrind isn't likely to catch it since it isn't a memory leak. This evil little rule likely goes all the way back to the old Unix string format, that didn't use null terminators. Pre-standard C used to allow such strings too, before C settled and was standardized.
– Lundin
Sep 18 '18 at 11:45
@Lundin OK, but this is a major problem. What happens with
a
in the printf()
call? Does a
get null terminated? If yes why there are still 10 chars?– Michi
Sep 18 '18 at 11:47
a
printf()
a
char b[10] = "1234567890";
doesn't contain a NUL-terminator so
char b[10] = "1234567890";
while ((*s++ = *t++));
does not terminate correctly (formally the program behaviour is undefined). Note that the constant "1234567890"
is a char[11]
type; the compiler allows you to assign it to a smaller array, with elements removed automatically.
"1234567890"
char[11]
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy
As an exercise, try to implement safe strcpy with char count - it should stop when number exceed n (10 in your case) - strnspy (en.cppreference.com/w/cpp/string/byte/strncpy).
– Alexey Voytenko
Sep 18 '18 at 11:25