1

I found an apparent contradiction in the c++ text having to do with the result of the c_str() function operating on std:strings (in my copy, the definition and contradiction are on p1040).

First it defines the c_str() function as something that produces a 'C-style' (zero-terminated) string, but later it talks about how a C++ c_str value can have embed a 'C'-style, end-of-string terminators (i.e. NUL's) embedded in the string (that is defined by being NUL terminated).

Um... does anyone else feel that this is a 'stretching' of the definition of a C-string beyond it's definition? I.e. I think what it means, is that if you were to look at the length() function as applied to the string, it will show a different end of string than using the C-definition of a z-string -- one that can contain any character except NUL, and is terminated by NUL.

I likely don't have to worry about it in my of my programs, but it seems like a subtle distinction that makes a C++ c_str, not really a 'C'-string. Am I misunderstanding this issue?

Thanks!

4
  • Zero is nul, if I'm not mistaken. May 28, 2014 at 19:31
  • 4
    It's quite possible that std::string::length() and strlen(std::string::c_str()) return different values if the string contains binary data. C_str does give a valid c-string, it just returns a pointer after all, you get the same effect if you do strlen("hello\0world")
    – James
    May 28, 2014 at 23:07
  • Robert Harvey@ - yes, I wasn't meaning to create a differentiation by using synonyms.
    – Astara
    May 29, 2014 at 1:23
  • James@ In 'C', a string cannot contain a NUL. Thus my objection to the term c-_str().
    – Astara
    May 29, 2014 at 1:24

2 Answers 2

6

The c_str function returns a pointer to the string's contents, ensuring that the data is followed by a NUL (zero) character.

┌─────────────data─────────────┐ end
48 65 6C 6C 6F 20 77 6F 72 6C 64 00
H  e  l  l  o  ␠   w  o  r  l  d  ␀

However, the string's data itself may contain a NUL character. (This is possible because std::string has to store its length explicitly instead of depending on null termination.) When this happens, strlen(str.c_str()) will return a smaller value than str.length().

┌─────────────data─────────────┐ end
48 65 6C 6C 6F 00 77 6F 72 6C 64 00
H  e  l  l  o  ␀   w  o  r  l  d  ␀
└────────────┘
 string seen by strlen() etc.

The above is the equivalent of doing strlen("Hello\0world") in C. The string as seen by the C function is a left-substring of the original string.

Sometimes this causes data loss or even a security risk, but what else could c_str() do in this situation?

1
  • 1
    This confirms what I asked. The thing is that I didn't like is calling a zero-containing string a 'C_str', since in C, you don't have length's and the only way to tell eol(or eos) is with a NUL/0. Thus, IMO, those are not real "C"-strings in that they wouldn't be displayed, via "printf", for example, the same way.
    – Astara
    May 29, 2014 at 1:21
3

In C, NULL is the same as 0x00. Or null is the same as zero.
And just to be clear, NUL is an equivalent name of NULL.

So Stroustrup's text is correct about how C++ c_str are terminated.


To provide a bit more context. It's fairly common practice in C to memset a character array after creating it in order to make sure it will be null terminated.

char foo[20];
memset(foo, 0x00, 20);
strlen(foo);  /* Should return 0 */

Please forgive me if my syntax is off a bit. And for the use of magic numbers.

2
  • Sorry if my question was unclear, but I was trying to use them as synonyms.
    – Astara
    May 29, 2014 at 1:25
  • NULL is most definitely not the same as 0x00 in C. It's an unspecified null-pointer-constant which can be implicitly converted to any pointer type. So (void*)0 and __builtin_null are perfectly fine. Feb 2, 2016 at 16:37

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.