This is my test code.
string str=string(\"def\");
const char* c_str=str.c_str();
char* charString=(char*)\"abc\";
char* target;
cout << \"str : \"<<
The line const char* c_str=str.c_str()
means:
c_str
.c_str
never contains the string but it contains a pointer/address (a 32 or 64 bit integer)
The sizeof(c_str)
returns the size used in memory by c_str
. In your case, you use a 64 bits compiler (so address are 64 bits). So c_str
returns 8
(we need 8 bytes of memory for storing 64 bits number).
Then *c_str
will give you the first character (ascii value) stored in the string. An ascii value is stored in a char and the memory needed for storing a char is 1
.
So sizeof(*c_str)
will always returns 1
.
It's why it's make no sense to write sizeof(c_str)/sizeof(*c_str)
. This expression is constant and will always returns 8/1 => 8 (nothing to do with the size of the string).
When you work with C string, it's better to use (strlen
, strcopy
, etc). Those functions will return you the excepted result.
sizeof(x)/(sizeof(*x)
is basically a mistake. The only way this basic construct makes sense is if x
is an array--but in this case, *x
only makes sense by converting the name of the array to a pointer to its first element (which, yes, does happen implicitly), then dividing by the size of that item.
At least theoretically, sizeof(x)/sizeof(x[0])
is a little better. There's no observable difference in actual use, but at least to somebody looking at it, the use of [0]
might provide some indication that this is really intended to be applied (only) to an array, not a pointer.
Assuming they are applied to arrays, they still have an effect that's fundamentally different from strlen
. strlen
assumes its argument is a NUL-terminated byte sequence. That means it counts bytes starting from the address you pass, until it encounters a byte containing the value '\0'
. That might be shorter than the array, or (if the array doesn't contain an NTBS) potentially much longer. In short, strlen
tries to tell you the current length of a string, whereas the sizeof(x)/sizeof(x[0])
attempts to tell you the maximum string size a particular array could potentially hold. These will coincide primarily when applied to an initialized array, like: char foo[] = "Something";
.
One other minor difference as well: strlen
only includes the number of characters before the terminating NUL, where sizeof(x)/sizeof(x[0])
includes all the storage of the array, one larger than the maximum length of NUL-terminated string you can store there.
If you apply either of these to a pointer instead of an array, you can plan on normally getting bad results (the "normally" weasel wording being to cover the corner case: if you happen to have an array exactly the same size as a pointer, it'll work, much like a broken clock giving the right time twice a day).
In C++, you're usually better off with something like this:
template <class T, size_t N>
constexpr size_t elements(T (&array)[N]) {
return N;
}
This requires that you pass it an array by reference. If you attempt to pass a pointer instead of an array, you'll get a compiler error instead of an incorrect answer.
Of course, in C++ you generally want to avoid using strlen
as well--you can normally use std::string
(or std::string_view
) and use its length()
or size()
member.