How can I get the real length of char*? Different between strlen and sizeof(target)/sizeof(target*)?

前端 未结 2 1731
南方客
南方客 2021-01-28 15:58

This is my test code.

string str=string(\"def\");
const char* c_str=str.c_str();
char* charString=(char*)\"abc\";
char* target;

cout << \"str : \"<<         


        
相关标签:
2条回答
  • 2021-01-28 16:11

    The line const char* c_str=str.c_str() means:

    1. Get the pointer/address (a 32 or 64 bits integer) of the memory used for storing the sring "def" (inside the str object).
    2. Store this pointer/address (a 32 or 64 bits integer) inside 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.

    0 讨论(0)
  • 2021-01-28 16:19

    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.

    0 讨论(0)
提交回复
热议问题