What's the difference between string::c_str() and string::data()?

M

Metro12

In the <basic_string.h>, I find the implementation of these two
functions. But I can't understand the difference between them.
Please give me some help!
//basic_string::c_str()
const _CharT*
c_str() const
{
// MT: This assumes concurrent writes are OK.
size_type __n = this->size();
traits_type::assign(_M_data()[__n], _Rep::_S_terminal);
return _M_data();
}

//basic_string::data()
const _CharT*
data() const { return _M_data(); }

Thanks!
 
B

Bob Hairgrove

In the <basic_string.h>, I find the implementation of these two
functions. But I can't understand the difference between them.
Please give me some help!
//basic_string::c_str()
const _CharT*
c_str() const
{
// MT: This assumes concurrent writes are OK.
size_type __n = this->size();
traits_type::assign(_M_data()[__n], _Rep::_S_terminal);
return _M_data();
}

//basic_string::data()
const _CharT*
data() const { return _M_data(); }

Thanks!

One is guaranteed by the C++ standard to be null-terminated, the other
isn't (but might be).
 
P

peter.koch.larsen

Metro12 skrev:
In the <basic_string.h>, I find the implementation of these two
functions. But I can't understand the difference between them.
Please give me some help!

A std::string is not null-terminated. While both functions return a
pointer to an array of the characters, std::string::c_str() make sure
that the array ends with \0.

/Peter

[snip]
 
B

Bob Hairgrove

In the <basic_string.h>, I find the implementation of these two
functions. But I can't understand the difference between them.
[snip]

One is guaranteed by the C++ standard to be null-terminated, the other
isn't (but might be).

Also, since std::string can contain binary data, including the null
character, the data() function would be more useful in those
situations. The pointer returned by c_str(), OTOH, is guaranteed to be
null-terminated and is typically used in legacy code which deals with
textual strings.

Although it would seem that c_str() could be used in either situation,
data() might NOT be null-terminated depending on the implementation.
 
M

Maxim Yegorushkin

Metro12 skrev:


A std::string is not null-terminated. While both functions return a
pointer to an array of the characters, std::string::c_str() make sure
that the array ends with \0.

Not null terminating std::string is impractical. We have yet to see a
std::string without null terminator.
 
P

peter.koch.larsen

Maxim Yegorushkin skrev:
Not null terminating std::string is impractical. We have yet to see a
std::string without null terminator.

This is an implementation-detail. I agree that the implementor of
std::string normally would reserve an extra char (and perhaps put \0 in
it) in order not to "get into troubles" if the user calls c_str.
But that 0 is not officially part of the string. Assume:

std::string s("Hello");
if (s[5] == '\0') ...

This last line is undefined behaviour although i would not be surprised
if the comparison was true.


/Peter
 
B

Bob Hairgrove

std::string s("Hello");
if (s[5] == '\0') ...

This last line is undefined behaviour although i would not be surprised
if the comparison was true.

On a conforming implementation, this throws std::eek:ut_of_range (see
21.3.4), therefore the behavior is defined.
 
K

krishanu.debnath

Maxim Yegorushkin skrev:

Not null terminating std::string is impractical. We have yet to see a
std::string without null terminator.

This is an implementation-detail. I agree that the implementor of
std::string normally would reserve an extra char (and perhaps put \0 in
it) in order not to "get into troubles" if the user calls c_str.
But that 0 is not officially part of the string. Assume:

std::string s("Hello");
if (s[5] == '\0') ...

This last line is undefined behaviour although i would not be surprised
if the comparison was true.

Why do you think last line invokes UB? Sec 21.3.4 clearly says that
behavior
is undefined only if index is greater than size().

Krishanu
 
P

peter.koch.larsen

Bob Hairgrove skrev:
std::string s("Hello");
if (s[5] == '\0') ...

This last line is undefined behaviour although i would not be surprised
if the comparison was true.

On a conforming implementation, this throws std::eek:ut_of_range (see
21.3.4), therefore the behavior is defined.

I do not use the constant of operator[]. I do not have the standard
myself, but according to Josuttis book this implies that my index
should be between 0 and s.size() - 1. So you claim is that Josuttis is
wrong? In that case I (and Josuttis ;-) will stand corrected.

/Peter
 
K

krishanu.debnath

Bob said:
std::string s("Hello");
if (s[5] == '\0') ...

This last line is undefined behaviour although i would not be surprised
if the comparison was true.

On a conforming implementation, this throws std::eek:ut_of_range (see
21.3.4), therefore the behavior is defined.

Which element access operator you are talking about? Here is what
standard says ..

21.3.4 - basic_string element access [lib.string.access]

const_reference operator[](size_type pos) const;
reference operator[](size_type pos);

-1- Returns: If pos < size(), returns data()[ pos ]. Otherwise, if pos
== size(), the const version returns charT(). Otherwise, the behavior
is undefined.

const_reference at(size_type pos) const;
reference at(size_type pos);

-2- Requires: pos < size()

-3- Throws: out_of_range if pos >= size().

-4- Returns: operator[]( pos ).

Krishanu
 
P

peter.koch.larsen

(e-mail address removed) skrev:
Maxim Yegorushkin skrev:

Not null terminating std::string is impractical. We have yet to see a
std::string without null terminator.

This is an implementation-detail. I agree that the implementor of
std::string normally would reserve an extra char (and perhaps put \0 in
it) in order not to "get into troubles" if the user calls c_str.
But that 0 is not officially part of the string. Assume:

std::string s("Hello");
if (s[5] == '\0') ...

This last line is undefined behaviour although i would not be surprised
if the comparison was true.

Why do you think last line invokes UB? Sec 21.3.4 clearly says that
behavior
is undefined only if index is greater than size().

Well - from my reading (a preliminary version on the net, but I doubt
that changes have been made in this area) it is clear to me that index
must be smaller than size() (or length() if you prefer) unless the
const version is called. Note that my code used the non-const
operator[].

/Peter
 
B

Bob Hairgrove

Bob Hairgrove skrev:
std::string s("Hello");
if (s[5] == '\0') ...

This last line is undefined behaviour although i would not be surprised
if the comparison was true.

On a conforming implementation, this throws std::eek:ut_of_range (see
21.3.4), therefore the behavior is defined.

I do not use the constant of operator[]. I do not have the standard
myself, but according to Josuttis book this implies that my index
should be between 0 and s.size() - 1. So you claim is that Josuttis is
wrong? In that case I (and Josuttis ;-) will stand corrected.

Oops, you are correct ... I was reading the details for the at()
function. Sorry for the confusion!

According to the operator[] description, it returns charT() if
pos==size().
 
B

Bob Hairgrove

Bob said:
std::string s("Hello");
if (s[5] == '\0') ...

This last line is undefined behaviour although i would not be surprised
if the comparison was true.

On a conforming implementation, this throws std::eek:ut_of_range (see
21.3.4), therefore the behavior is defined.

Which element access operator you are talking about? Here is what
standard says ..

21.3.4 - basic_string element access [lib.string.access]

const_reference operator[](size_type pos) const;
reference operator[](size_type pos);

-1- Returns: If pos < size(), returns data()[ pos ]. Otherwise, if pos
== size(), the const version returns charT(). Otherwise, the behavior
is undefined.

const_reference at(size_type pos) const;
reference at(size_type pos);

-2- Requires: pos < size()

-3- Throws: out_of_range if pos >= size().

-4- Returns: operator[]( pos ).

Yes, I was looking at the description for the at() function. Sorry!
 
L

Larry I Smith

Maxim said:
Not null terminating std::string is impractical. We have yet to see a
std::string without null terminator.

Most of our std::string usage is to hold binary data (image files,
etc). Automatically nul-terminating a std::string is of no
particular use. Use c_str() if a nul-terminated version is needed,
or data() if you merely need access to the raw bytes; in either case
length() gives the actual data length (whether or not the raw data
is binary data).

Regards,
Larry
 
O

Old Wolf

Maxim said:
Not null terminating std::string is impractical. We have yet to see a
std::string without null terminator.

I have read that standard library implementations maintain
a counted string, and only append a \0 when someone calls c_str().

I don't see how it is more practical for an implementation to
have to manipulate zeroes all the time, it would seem to me
that it's easier just to deal with the counted number of bytes.
 
K

krishanu.debnath

(e-mail address removed) skrev:

std::string s("Hello");
if (s[5] == '\0') ...

This last line is undefined behaviour although i would not be surprised
if the comparison was true.

Why do you think last line invokes UB? Sec 21.3.4 clearly says that
behavior
is undefined only if index is greater than size().

Well - from my reading (a preliminary version on the net, but I doubt
that changes have been made in this area) it is clear to me that index
must be smaller than size() (or length() if you prefer) unless the

We can only justify the behavior by whats written in standard, not by
any
material you see on net.

Krishanu
 
P

peter.koch.larsen

(e-mail address removed) skrev:
(e-mail address removed) skrev:

std::string s("Hello");
if (s[5] == '\0') ...

This last line is undefined behaviour although i would not be surprised
if the comparison was true.

Why do you think last line invokes UB? Sec 21.3.4 clearly says that
behavior
is undefined only if index is greater than size().

Well - from my reading (a preliminary version on the net, but I doubt
that changes have been made in this area) it is clear to me that index
must be smaller than size() (or length() if you prefer) unless the

We can only justify the behavior by whats written in standard, not by
any
material you see on net.

Well... most of the draft standard on the net is pretty accurate. But
let me quote the standard quote from one of your other posts in this
thread:

<begin quote>
21.3.4 - basic_string element access [lib.string.access]


const_reference operator[](size_type pos) const;
reference operator[](size_type pos);


-1- Returns: If pos < size(), returns data()[ pos ]. Otherwise, if pos
== size(), the const version returns charT(). Otherwise, the behavior
is undefined.

<end quote>

This part is word by word the same as the draft I read. Clearly both
quotes support my view:
std::string s("Hello");
if (s[5] == '\0') ...

This last line is undefined behaviour although i would not be surprised
if the comparison was true.

/Peter
 
K

krishanu.debnath

(e-mail address removed) skrev:
(e-mail address removed) skrev:

std::string s("Hello");
if (s[5] == '\0') ...

This last line is undefined behaviour although i would not be surprised
if the comparison was true.

Why do you think last line invokes UB? Sec 21.3.4 clearly says that
behavior
is undefined only if index is greater than size().

Well - from my reading (a preliminary version on the net, but I doubt
that changes have been made in this area) it is clear to me that index
must be smaller than size() (or length() if you prefer) unless the

We can only justify the behavior by whats written in standard, not by
any
material you see on net.

Well... most of the draft standard on the net is pretty accurate. But
let me quote the standard quote from one of your other posts in this
thread:

<begin quote>
21.3.4 - basic_string element access [lib.string.access]


const_reference operator[](size_type pos) const;
reference operator[](size_type pos);


-1- Returns: If pos < size(), returns data()[ pos ]. Otherwise, if pos
== size(), the const version returns charT(). Otherwise, the behavior
is undefined.

<end quote>

This part is word by word the same as the draft I read. Clearly both
quotes support my view:

My goof. I overlook the words 'const version'.

Krishanu
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top