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)






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







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

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)