You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

C++数组的数组定义方法及VS2015编译错误修复方案

解决VS2015中constexpr数组初始化的编译器内部错误及类型不匹配问题

这个问题我之前碰到过,VS2015对constexpr C风格数组的聚合初始化确实存在兼容性bug。咱们先拆解下问题根源:你定义的myTypeuint8_t[16]这种C风格数组类型,当尝试把x0x1x2这些constexpr数组放进AllX数组时,IntelliSense会误把数组退化为指针(const uint8_t*),和AllX期望的const uint8_t[][16]类型不匹配;而编译器报内部错误,则是VS2015对这种constexpr数组聚合初始化的支持不完善导致的。

下面给你两种可行的解决办法:

方法一:改用std::array替代C风格数组(推荐

std::array是C++11引入的容器,本质是封装了C风格数组的类类型,VS2015对它的constexpr支持稳定得多。修改后的代码如下:

#include <array>
#include <cstdint>

using myType = std::array<uint8_t, 16>;
constexpr myType x0 = {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6};
constexpr myType x1 = {11,12,13,14,15,16,17,18,19,10,11,12,13,14,15,16};
constexpr myType x2 = {21,22,23,24,25,26,27,28,29,20,21,22,23,24,25,26};
constexpr std::array<myType, 3> AllX = {x0, x1, x2};

这种写法完全符合C++标准,既能避开VS2015的编译器bug,IntelliSense也不会再报错,而且代码可读性和维护性都更好。

方法二:手动展开C风格数组的初始化(兼容原有类型)

如果因为项目限制必须使用C风格数组,可以直接把每个数组的元素手动展开到AllX中,绕开数组到数组的初始化逻辑:

#include <cstdint>

typedef uint8_t myType[16];
constexpr myType x0 = {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6};
constexpr myType x1 = {11,12,13,14,15,16,17,18,19,10,11,12,13,14,15,16};
constexpr myType x2 = {21,22,23,24,25,26,27,28,29,20,21,22,23,24,25,26};
// 手动展开每个数组的元素进行初始化
constexpr uint8_t AllX[3][16] = {
    {x0[0], x0[1], x0[2], x0[3], x0[4], x0[5], x0[6], x0[7], x0[8], x0[9], x0[10], x0[11], x0[12], x0[13], x0[14], x0[15]},
    {x1[0], x1[1], x1[2], x1[3], x1[4], x1[5], x1[6], x1[7], x1[8], x1[9], x1[10], x1[11], x1[12], x1[13], x1[14], x1[15]},
    {x2[0], x2[1], x2[2], x2[3], x2[4], x2[5], x2[6], x2[7], x2[8], x2[9], x2[10], x2[11], x2[12], x2[13], x2[14], x2[15]}
};

这种方法虽然繁琐,但能在VS2015中正常编译,保持原有C风格数组的类型不变。

另外提一句:如果你的项目允许升级编译器,VS2017及以后的版本已经修复了这个constexpr数组的编译器内部错误,直接使用你原来的代码就能正常编译通过。

内容的提问来源于stack exchange,提问作者mans

火山引擎 最新活动