c ++中编译时的静态字符数组大小

时间:2012-05-04 20:14:53

标签: c++

我知道这个问题多次问过,我不会问怎么做,因为我是在编译时这样做的。我的问题是它是如何工作的,因为这是我不理解的。

当将char[]传递给函数时,它会丢失其信息并变为char*,因此我们无法在编译时使用模板获取字符数组的大小,所以我尝试并传递了字符串本身就有用了:

template <int N> inline int arr_len(const char (&)[N]) { return N - 1; }

#define STR "this is an example!"

const char *str_ptr = STR;

int main()
{
  int array_size = arr_len(STR);
}

我使用VC ++ 2008,英特尔C ++ 12和GCC 4.7测试了这段代码,它可以运行。

通过传递字符串本身,编译器将其视为const char[] - 至少我认为 - 并且他能够获得字符串大小,这怎么可能?

3 个答案:

答案 0 :(得分:3)

字符串文字类型是一个数组,而不是指针。因此,当您将其直接传递给通过引用获取数组的函数时,它不会衰减为指针。

答案 1 :(得分:1)

这是因为STR是一个在编译器启动之前被替换的宏。

它将其替换为“XXXX”,它是一个字符串文字(不是数组)。

要使其发挥作用,请执行以下操作:

char const  str_ptr[] = "XXX YYY";
              //  ^^^^    Compiler works out size

int main()
{
    int array_size = arr_len(str_ptr);
                         //  ^^^^^^^ pass in an object that has a type.
};

答案 2 :(得分:0)

在C ++中,当函数的参数类型暂时被识别为数组时,参数类型被调整为&#39;是一个指向数组元素类型的指针。

因此,当您编写:void foo(char c[])时,编译器会将其有效地重写为void foo(char *c)。然后当你传递一个数组时:

char x[10];
foo(x);

C ++找到void foo(char *c)并发现它可以将您的char []参数转换为char *并调用该函数,这正是它所做的。

但是,只有当写入的参数类型是数组时,才会对函数类型进行此调整。对数组的引用不是数组,因此在声明函数void bar(char (&c)[10])时不会执行等效调整。

回答你的问题需要的第二点是字符串文字的类型是一个const char数组。当您在函数调用中直接编写字符串文字时,使用const char (&)[N] C ++的函数可以看到它可以传递对数组的引用,而不是执行&#34;数组 - &gt;指向第一个元素的指针&#34;转换。这就是它的作用,模板类型推导找到了正确的字符串大小的数字。