14

I am quite anxious about strings in C. Do I need to set the last char \0 or it does it by it self? If I don't do it manually then when I try to debug code and when I access string1[257] it is not null. I am having problems with freeing allocated memory of an array of strings so I thought it was a reason.

char string1[257], string2[257];
scanf("%s", &string2);
string1[257] = '\0';
strncpy(string1, string2, 257);
string1[257] = '\0'; /* do I need to do that? */
1
  • 15
    Note that if you declare char[257] the index goes from 0 to 256. Commented Nov 20, 2011 at 16:28

5 Answers 5

14

String literals like "Hello World!" are null-terminated, but char arrays are not automatically null terminated.

The general principle I've always taken is to be extra cautious and assign '\0' to the the end of the string unless that causes a performance problem. In those cases, I'm extra careful about which library functions I use.

Sign up to request clarification or add additional context in comments.

5 Comments

That's \0 (NUL), not NULL.
And yet NULL, 0, and '\0' have distinct meanings. No need to conflate them just because a language designed 30 years ago allows you to.
Not necessarily, NULL may be defined as ((void*)0). In any case, these are different concepts that should not be conflated.
@larsmans - Ah, yes, NULL may be a 0 cast to a void* so it may not work.
You statement about arrays depends on how it's initialized. Consider char str[4] = "test" vs char str[] = "test".
7

Always be careful to allocate enough memory with strings, compare the effects of the following lines of code:

char s1[3] = "abc";
char s2[4] = "abc";
char s3[] = "abc";

All three are considered legal lines of code (http://c-faq.com/ansi/nonstrings.htmlhttp://c-faq.com/ansi/nonstrings.html), but in the first case, there isn't enough memory for the fourth null-terminated character. s1 will not behave like a normal string, but s2 and s3 will. The compiler automatically count for s3, and you get four bytes of allocated memory. If you try to write

s1[3] = '\0';

that's undefined behavior and you're writing to memory that doesn't belong to s1, and would have weird effects, maybe even disrupting malloc's backend information, making it hard to free memory.

Comments

3

A literal string like "foo\nbar" is always translated to a const char literal[] with an additional zero byte at the end. (So the constant would have 8 bytes, the first being f and the last being zero).

But you are right in forcing explicitly the last byte to 0 after a strncpy.

And as Aurelio De Rosa remarked, the last correct index is 256 for an array [257].

Comments

2

Yes, you need to do that. Not all functions put the null char for you, and strncpy, as I can read in its man page, requires to have a null byte among the first n characters of src.

1 Comment

strncpy is a rather "special" function with special semantics. Usually not what people want when they're just copying strings around, unfortunately.
1

Is it absolutely necessary? No, because when you call scanf, strcpy(except for strncpy where you need to manually put zero if it exceeds the size), it copies the null terminator for you. Is it good to do it anyways? Not really, it doesn't really help the problem of bufferoverflow since those function will go over the size of the buffer anyways. Then what's the best way? use c++ with std::string.

By the way, if you access/write to string1[257], that will be out of bound since you're accessing/writing 258th element in an array of size 257. (it's 0-based index)

2 Comments

strncpy may not copythe null terminator. See stackoverflow.com/questions/1453876/…
oh. that makes sense about accessing 258th element. thank you sir.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.