为何MinGW编译代码时报“无法用float (*)[in_dim]右值初始化同类型变量”
解决MinGW编译C++变长数组指针报错问题
问题原因
你遇到的编译错误,本质是C++标准不允许使用运行时变量作为数组维度来定义指针数组(即变长数组VLA)。之前用g编译没问题,是因为GCC自带了支持变长数组的扩展;但MinGW在默认的C编译模式下未启用该扩展,因此CLion中会抛出类型不匹配的错误。
解决方案
方案1:启用GCC的变长数组扩展
直接通过编译选项开启GCC扩展,让MinGW兼容原有写法:
- 在CLion的CMake配置中添加选项:
- 打开
File -> Settings -> Build, Execution, Deployment -> CMake - 在
CMake options中加入:-DCMAKE_CXX_FLAGS="-fpermissive"
- 打开
- 或者在CMakeLists.txt中给目标添加编译选项:
target_compile_options(你的项目目标名 PRIVATE -fpermissive)
- 也可以将C++标准设置为GNU扩展版本(如
gnu++17而非c++17),在CMakeLists.txt中添加:
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS ON)
方案2:改用标准C++写法(推荐)
如果想让代码符合C++标准,避免依赖编译器扩展,可通过以下方式修改:
方式A:直接计算数组索引(无额外开销)
跳过二维指针转换,直接通过一维数组的索引计算访问元素,逻辑与原代码完全一致:
void XW(int in_dim, int out_dim, float *in_X, float *out_X, float *W) { for (int i = 0; i < v_num; i++) { for (int j = 0; j < out_dim; j++) { float sum = 0.0f; for (int k = 0; k < in_dim; k++) { sum += in_X[i * in_dim + k] * W[k * out_dim + j]; } out_X[i * out_dim + j] += sum; } } } void AX(int dim, float *in_X, float *out_X) { for (int i = 0; i < v_num; i++) { vector<int> &nlist = edge_index[i]; for (int j = 0; j < nlist.size(); j++) { int nbr = nlist[j]; float val = edge_val[i][j]; for (int k = 0; k < dim; k++) { out_X[i * dim + k] += in_X[nbr * dim + k] * val; } } } }
方式B:用C++20 std::span创建视图(无拷贝)
若使用C++20及以上版本,可通过std::span创建二维数组视图,提升代码可读性:
#include <span> void XW(int in_dim, int out_dim, float *in_X, float *out_X, float *W) { auto get_row = [](float* arr, int row_size, int row_idx) -> std::span<float> { return std::span<float>(arr + row_idx * row_size, row_size); }; for (int i = 0; i < v_num; i++) { auto out_row = get_row(out_X, out_dim, i); auto in_row = get_row(in_X, in_dim, i); for (int j = 0; j < out_dim; j++) { float sum = 0.0f; for (int k = 0; k < in_dim; k++) { sum += in_row[k] * get_row(W, out_dim, k)[j]; } out_row[j] += sum; } } }
方式C:用std::vector包装(有拷贝开销,适合小数据)
若不介意数据拷贝,可直接用std::vector创建二维数组,代码最直观:
#include <vector> #include <algorithm> void XW(int in_dim, int out_dim, float *in_X, float *out_X, float *W) { std::vector<std::vector<float>> tmp_in_X(v_num); std::vector<std::vector<float>> tmp_W(in_dim); std::vector<std::vector<float>> tmp_out_X(v_num, std::vector<float>(out_dim, 0.0f)); for (int i = 0; i < v_num; i++) { tmp_in_X[i].resize(in_dim); std::copy(in_X + i*in_dim, in_X + (i+1)*in_dim, tmp_in_X[i].begin()); } for (int i = 0; i < in_dim; i++) { tmp_W[i].resize(out_dim); std::copy(W + i*out_dim, W + (i+1)*out_dim, tmp_W[i].begin()); } for (int i = 0; i < v_num; i++) { for (int j = 0; j < out_dim; j++) { for (int k = 0; k < in_dim; k++) { tmp_out_X[i][j] += tmp_in_X[i][k] * tmp_W[k][j]; } } } for (int i = 0; i < v_num; i++) { std::copy(tmp_out_X[i].begin(), tmp_out_X[i].end(), out_X + i*out_dim); } }
内容的提问来源于stack exchange,提问作者Closure
相关产品推荐
相关产品推荐

