一个常量字符数组的字符串长度函数(strlen)不是常量表达式

6

让我们直接看简化后的代码(编译器:GCC 6.3.0)

#include<iostream>
#include<cstring>

using namespace std;

int main(int arga, char* argv[]) {

    const char cs[] = "Hello";//define a constant c-style string 
    constexpr size_t newSize = strlen(cs) + strlen(" ");//Error

    return 0;
}

编译器报错: strlen(((const char*)(& cs))) 不是一个常量表达式。但是,当我将C字符串定义移到全局范围时,问题就解决了。
.... 
const char cs[] = "Hello";

int main(int arga, char* argv[]) {
    constexpr size_t newSize = strlen(cs) + strlen(" ")//No Error
 ....
}

有人能解释一下发生了什么吗?为什么 strlen() 将一个全局定义的常量字符串视为常量表达式,但不是栈中的那个?


2
我对constexpr了解不多,只是好奇当字符串本身不是constexpr时,它的大小如何可以是constexpr - 463035818_is_not_a_number
1
我知道GCC有一些函数,比如strlen,它会被视为内置函数,除非你传递一个标志来禁用它。也许这只适用于具有静态存储期的字符串。 - chris
1
Clang 拒绝了这段代码。 - NathanOliver
GCC 6.3.0 被使用。 - SLN
1
@user463035818,我相信字符串可以像const int i = 5; int arr[i];中的i一样,在常量表达式中使用,尽管没有constexpr关键字。给定一个constexpr形式的strlen函数,为了使指针转换正确工作,字符串必须具有静态存储期。如果你避免该转换(例如通过自己编写接受const char(&)[N]strlen函数),我认为它无论存储期如何都可以正常工作。我希望得到一个有坚实支持的答案,而我目前无法做到这一点。 - chris
显示剩余2条评论
1个回答

7

标准的strlen不是constepxr,因此不能在constexpr上下文中使用。然而,GCC知道strlen的信息,因此在某些情况下,即使标准没有规定/允许,它仍能计算字符串的长度。

如果你只关心数组,可以使用std::size来获取它们的大小:

template <class T, std::size_t N>
constexpr std::size_t size(const T (&array)[N]) noexcept
{
    return N;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接