如何获得char *的实际长度? strlen和sizeof(target)/ sizeof(target *)之间有什么不同?

时间:2017-06-16 01:43:47

标签: c++ arrays

这是我的测试代码。

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

cout << "str : "<< str<< endl;
cout << "c_str : "<< c_str << endl;
cout << "charString : " << charString << endl << endl;


cout << "string length : " << str.length() << endl;
cout << "c_str length : " << strlen(c_str) << endl;
cout << "c_str array length : " << (sizeof(c_str)/sizeof(*c_str)) << endl;
cout << "charString length : " << strlen(charString) << endl;
cout << "charString array length " << (sizeof(charString)/sizeof(*charString)) << endl<< endl;

target = (char*) malloc(sizeof(char)*2);
target = (char*)"ab";
cout << "target : " << target << endl;
cout << "target strlen : " << strlen(target) << endl;
cout << "target arr length : " << (sizeof(target)/sizeof(char)) << endl;

这是上述代码的结果。

str : def
c_str : def
charString : abc

string length : 3
c_str length : 3
c_str array length : 8
charString length : 3
charString array length 8

target : ab
target strlen : 2
target arr length : 8

在str,c_str,charString的情况下,strlen为3,数组长度为8。 8包括编码和&#39; \ 0&#39;性格终于来了。正确?

所以,我真的不了解目标案例。

我分配内存2字节。 并分配2个字符。 strlen是对的。

  • 但为什么目标数组长度为8,如c_str和charString的数组长度?为什么目标的数组长度不小于c_str和charString?

  • 最后一个问题,我在邮件标题中发送消息char *,包括消息长度。如果我想从string.c_str()计算消息长度,我是否必须计算(sizeof(target)/ sizeof(* target))?

2 个答案:

答案 0 :(得分:5)

sizeof(x)/(sizeof(*x) 基本上是一个错误。这个基本结构有意义的唯一方法是x是一个数组 - 但在这种情况下,*x只有通过将数组的名称转换为指向其第一个元素的指针才有意义(是的,确实发生了隐式),然后除以该项目的大小。

至少在理论上,sizeof(x)/sizeof(x[0])稍好一点。在实际使用中没有可观察到的差异,但至少对于看到它的人来说,使用[0]可能会提供一些迹象表明这实际上是打算(仅)应用于数组,而不是指针。

假设它们已应用于数组,它们仍然具有与strlen根本不同的效果。 strlen假设其参数是NUL终止的字节序列。这意味着它从您传递的地址开始计算字节数,直到遇到包含值'\0'的字节为止。这可能比数组短,或者(如果数组不包含NTBS)可能更长。简而言之,strlen会尝试告诉您字符串的当前长度,而sizeof(x)/sizeof(x[0])会尝试告诉您可能可能保留的特定数组的最大字符串大小。当应用于初始化数组时,这些将主要重合,例如:char foo[] = "Something";

另外还有一个细微差别:strlen仅包括终止NUL之前的字符数,其中sizeof(x)/sizeof(x[0])包含数组的所有存储空间,一个大于你可以存储在那里的NUL终止字符串的最大长度。

如果你将其中任何一个应用于指针而不是数组,你可以计划通常得到不好的结果(通常&#34;通常&#34;黄鼠狼的措辞是为了覆盖角落的情况:如果你碰巧有一个数组与指针的大小完全相同,它可以正常工作,就像一个破碎的时钟,每天两次正确的时间)。

在C ++中,你通常会更喜欢这样的事情:

template <class T, size_t N>
constexpr size_t elements(T (&array)[N]) {
    return N;
}

这要求您通过引用传递数组。如果您尝试传递指针而不是数组,则会收到编译器错误而不是错误的答案。

当然,在C ++中,您通常也希望避免使用strlen - 您通常可以使用std::string(或std::string_view)并使用其length()或{ {1}}成员。

答案 1 :(得分:1)

const char* c_str=str.c_str()表示:

  1. 获取用于存储sring&#34; def&#34;的内存的指针/地址(32或64位整数)。 (在str对象内)。
  2. 将此指针/地址(32或64位整数)存储在c_str内。
  3. c_str从不包含字符串,但它包含pointer/address (a 32 or 64 bit integer)

    sizeof(c_str)返回c_str内存中使用的大小。在您的情况下,您使用64位编译器(因此地址是64位)。所以c_str返回8(我们需要8个字节的内存来存储64位数字)。

    然后*c_str将为您提供存储在字符串中的第一个字符(ascii值)。 ascii值存储在char中,存储char所需的内存为1

    因此sizeof(*c_str)将始终返回1。 这就是为什么写sizeof(c_str)/sizeof(*c_str)没有意义。此表达式是常量,将始终返回8/1 =&gt; 8(与字符串的大小无关)。

    使用C字符串时,最好使用(strlenstrcopy等)。这些功能将返回例外结果。