在 C++ 中获取 const char * 长度的最佳方法
Best way to get length of const char * in c++
我知道两种获取 const char 长度的方法 *
const char * str = "Hello World !";
int Size = 0;
while (str[Size] != '[=10=]') Size++;
其他方式很简单
const char * str = "Hello World !";
size_t Size = strlen(str);
但我不想使用像 strlen
这样的 str lib 函数,我认为这个函数也使用了我的第一种方式行为。因为在 PC 世界中,当我们想要计算某些东西时,我们需要计算每个块的数量,并且没有魔法可以通过一次移动获得长度,所以我认为第一种方法是获得 const char *
长度的最佳选择。其他方式我认为第一种方式对于重弦来说可能太重了。所以我很困惑。哪种方式更好,为什么其他方式不好?
让我们检查一下这两个方法的汇编列表。
#include <cstddef>
#include <cstring>
int string_size_1()
{
const char * str = "Hello World !";
int Size = 0;
while (str[Size] != '[=10=]') Size++;
return Size;
}
int string_size_2()
{
const char * str = "Hello World !";
size_t Size = strlen(str);
return Size;
}
使用带标志的 Clang 4.0.0 -std=c++14 -O2
string_size_1(): # @string_size_1()
mov eax, 13
ret
string_size_2(): # @string_size_2()
mov eax, 13
ret
Link: https://godbolt.org/g/5S6VSZ
两种方法都以完全相同的程序集列表结束。此外,编译器优化了所有内容,只优化了 return 一个常量,因为字符串文字在编译时是已知的。所以,就性能而言,它们同样优秀。
但是就可读性而言,strlen(str)
肯定更好。函数调用通过函数名称表明意图。循环不能做到这一点。
此外,std::string
和std::string_view
在很多情况下比C-string更受欢迎。考虑一下。
在这种情况下,答案在编译时已知:
template <std::size_t S>
constexpr std::size_t string_length
(
char const (&)[S]
)
{
return S - 1;
}
用法:
std::cout << string_length("example") << std::endl;
对于字符串不是编译时常量的情况,如果只有指向字符串的指针可用,则使用 strlen;如果指向开始和结束的指针都可用,则 std::distance;如果指向开始和结束的指针都可用,则使用 .size()你处理的是 std::string
晚了 3 年,但迟到总比没有好。
简答
#define length(array) ((sizeof(array)) / (sizeof(array[0])))
长答案
所以使用 sizeof(array)
returns the size of the type of the array
* the amount of elements
。知道了这一点,我们就可以做到这一点:
#define length(array) ((sizeof(array)) / (sizeof(array[0])))
你会像这样使用它:
type yourArray[] = {your, values};
length(yourArray); // returns length of yourArray
例如:
#include <stdlib.h>
#include <stdio.h>
#define length(array) ((sizeof(array)) / (sizeof(array[0])))
int main()
{
const char *myStrings[] = {"Foo", "Bar", "Hello, World!"}; // 3 elements
int myNums[] = {0, 1, 5, 7, 11037}; // 5 elements
char myChars[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'}; // 7 elements
printf("Length of myStrings array: %lu\n", length(myStrings));
printf("Length of myNums array: %lu\n", length(myNums));
printf("Length of myChars array: %lu\n", length(myChars));
return 0;
/* Output:
Length of myStrings array: 3
Length of myNums array: 5
Length of myChars array: 7 */
}
我测试了它,它也适用于未初始化的数组,可能是因为它们包含来自同一类型的垃圾(未初始化)。未初始化的整数数组包含随机整数,const char* 未初始化的数组包含 (null),它被视为 const char*.
现在,这只适用于堆栈上的数组。指向用作数组的堆中保留的 space 的指针会产生意想不到的结果。例如:
int *myNums = (int *)malloc(3 * sizeof(int)); // Space for 3 integers
printf("Length of myNums: %lu\n", length(myNums)); // Outputs 2 instead of 3
请注意。无论如何,谁在堆上使用数组。
注意: 这与此问题相关,因为它按要求与 const char * 一起使用。也适用于其他类型。
我知道两种获取 const char 长度的方法 *
const char * str = "Hello World !";
int Size = 0;
while (str[Size] != '[=10=]') Size++;
其他方式很简单
const char * str = "Hello World !";
size_t Size = strlen(str);
但我不想使用像 strlen
这样的 str lib 函数,我认为这个函数也使用了我的第一种方式行为。因为在 PC 世界中,当我们想要计算某些东西时,我们需要计算每个块的数量,并且没有魔法可以通过一次移动获得长度,所以我认为第一种方法是获得 const char *
长度的最佳选择。其他方式我认为第一种方式对于重弦来说可能太重了。所以我很困惑。哪种方式更好,为什么其他方式不好?
让我们检查一下这两个方法的汇编列表。
#include <cstddef>
#include <cstring>
int string_size_1()
{
const char * str = "Hello World !";
int Size = 0;
while (str[Size] != '[=10=]') Size++;
return Size;
}
int string_size_2()
{
const char * str = "Hello World !";
size_t Size = strlen(str);
return Size;
}
使用带标志的 Clang 4.0.0 -std=c++14 -O2
string_size_1(): # @string_size_1()
mov eax, 13
ret
string_size_2(): # @string_size_2()
mov eax, 13
ret
Link: https://godbolt.org/g/5S6VSZ
两种方法都以完全相同的程序集列表结束。此外,编译器优化了所有内容,只优化了 return 一个常量,因为字符串文字在编译时是已知的。所以,就性能而言,它们同样优秀。
但是就可读性而言,strlen(str)
肯定更好。函数调用通过函数名称表明意图。循环不能做到这一点。
此外,std::string
和std::string_view
在很多情况下比C-string更受欢迎。考虑一下。
在这种情况下,答案在编译时已知:
template <std::size_t S>
constexpr std::size_t string_length
(
char const (&)[S]
)
{
return S - 1;
}
用法:
std::cout << string_length("example") << std::endl;
对于字符串不是编译时常量的情况,如果只有指向字符串的指针可用,则使用 strlen;如果指向开始和结束的指针都可用,则 std::distance;如果指向开始和结束的指针都可用,则使用 .size()你处理的是 std::string
晚了 3 年,但迟到总比没有好。
简答
#define length(array) ((sizeof(array)) / (sizeof(array[0])))
长答案
所以使用 sizeof(array)
returns the size of the type of the array
* the amount of elements
。知道了这一点,我们就可以做到这一点:
#define length(array) ((sizeof(array)) / (sizeof(array[0])))
你会像这样使用它:
type yourArray[] = {your, values};
length(yourArray); // returns length of yourArray
例如:
#include <stdlib.h>
#include <stdio.h>
#define length(array) ((sizeof(array)) / (sizeof(array[0])))
int main()
{
const char *myStrings[] = {"Foo", "Bar", "Hello, World!"}; // 3 elements
int myNums[] = {0, 1, 5, 7, 11037}; // 5 elements
char myChars[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'}; // 7 elements
printf("Length of myStrings array: %lu\n", length(myStrings));
printf("Length of myNums array: %lu\n", length(myNums));
printf("Length of myChars array: %lu\n", length(myChars));
return 0;
/* Output:
Length of myStrings array: 3
Length of myNums array: 5
Length of myChars array: 7 */
}
我测试了它,它也适用于未初始化的数组,可能是因为它们包含来自同一类型的垃圾(未初始化)。未初始化的整数数组包含随机整数,const char* 未初始化的数组包含 (null),它被视为 const char*.
现在,这只适用于堆栈上的数组。指向用作数组的堆中保留的 space 的指针会产生意想不到的结果。例如:
int *myNums = (int *)malloc(3 * sizeof(int)); // Space for 3 integers
printf("Length of myNums: %lu\n", length(myNums)); // Outputs 2 instead of 3
请注意。无论如何,谁在堆上使用数组。
注意: 这与此问题相关,因为它按要求与 const char * 一起使用。也适用于其他类型。