如何获取字符*的实际长度?strlen 和 sizeof(target)/sizeof(target*)之间的区别?

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

本文关键字:sizeof target strlen 区别 之间 获取 何获取 字符      更新时间:2023-10-16

这是我的测试代码。

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 最后包括编码和"\0"字符。右?

所以,我真的不明白目标情况。

我分配内存 2 字节。 并分配 2 个字符。 斯特伦是对的。

  • 但是为什么目标数组长度是 8,就像 c_str 和 charString 的数组长度一样?为什么目标的数组长度不小于 c_str 和 charString?

  • 最后一个问题,我发送消息字符*,包括消息头中的消息长度。如果我想从 string.c_str() 计算消息长度,我是否必须像 (sizeof(target)/sizeof(*target)) 一样计算?

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

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

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

还有一个小区别:strlen只包括终止 NUL之前的字符数,其中sizeof(x)/sizeof(x[0])包括数组的所有存储,一个大于您可以存储在那里的 NUL 终止字符串的最大长度。

如果你将这些中的任何一个应用于指针而不是数组,你可以计划通常得到不好的结果("通常"的鼬鼠措辞是为了覆盖极端情况:如果你碰巧有一个与指针大小完全相同的数组,它会工作,就像一个坏掉的时钟每天两次给出正确的时间)。

在C++,你通常最好这样:

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

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

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

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

  1. 获取用于存储 sring "def"(在 str 对象内部)的内存的指针/地址(32 或 64 位整数)。
  2. 将此指针/地址(32 或 64 位整数)存储在c_str内。

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 值存储在字符中,存储字符所需的内存1

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

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