Как передать динамический 2-D массив в функцию в переполнении стека

Я пытаюсь передать динамический 2-D массив в функцию, и он выдает ошибку. Я попытался явно указать размеры массива, и это сработало, но динамический не работает, никаких указателей (каламбур не предназначен)

#include <iostream>
#include <vector>

using namespace std;

void print_2d_array(int arr_size, int (*arr)[5]){
for(int i = 0; i < arr_size; ++i){
for(int j = 0; j < arr_size; ++j)
cout << arr[i][j] << "\t";
cout << endl;
}
}

int main(){
vector<int> x{10,15,20,30,40};
int arr[x.size()][x.size()];

for(int i = 0; i < x.size(); ++i)
arr[i][i] = 0;

print_2d_array(5, arr);
return 0;
}

Я перепробовал все три метода, которые были подробно описаны здесь Передача 2D массива в C

Если вместо создания экземпляра массива, как показано выше, я использую что-то вроде

arr[5][5];

это работает как ожидалось. Я получаю следующую ошибку

error: cannot convert ‘int (*)[(<anonymous> + 1)]’ to ‘int (*)[5]’ for argument ‘2’
to ‘void print_2d_array(int, int (*)[5])’

print_2d_array (5, обр);

0

Решение

Массив переменной длины (VLA) не является частью стандарта C ++. Он является частью стандарта C99 и обычно реализуется как расширение для C ++ в различных компиляторах.

Обычно нормально использовать VLA в программе C ++, когда вы выделяете массив. Но у вас будут проблемы, когда вам нужно будет передать массив, потому что нет типа аргумента, который является VLA, чтобы вы могли передавать его в качестве аргументов функциям в C ++. (Вот почему, когда вы вручную вставляете функцию, код работает нормально, что позволяет избежать передачи массива в функцию.) Вы должны передать массив как указатель на функцию и, возможно, использовать reinterpret_cast до и внутри функции для преобразования VLA в указатель и преобразования его обратно. Это просто ужасный код.

При кодировании на C ++ просто используйте идиоматический способ C ++. Поскольку вы уже используете vectorВы можете просто использовать vector<vector<int>> (vector<vector<int> > если не с использованием C ++ 11, а из способа инициализации xвы используете C ++ 11) в качестве двумерного массива. Ваш код должен быть изменен, как показано ниже:

#include <iostream>
#include <vector>

using namespace std;

void print_2d_array(int arr_size, vector<vector<int>> &arr){
for(int i = 0; i < arr_size; ++i){
for(int j = 0; j < arr_size; ++j)
cout << arr[i][j] << "\t";
cout << endl;
}
}

int main(){
vector<int> x{10,15,20,30,40};
vector<vector<int>> arr(x.size(), vector<int>(x.size()));

// No need to use this to initialize:
// for(int i = 0; i < sizeof(x); ++i)
//     arr[i][i] = 0;

print_2d_array(5, arr);
return 0;
}

Обратите внимание, что это также исправило вашу проблему arr не был правильно инициализирован.

Если вы собираетесь использовать C, то с VLA все в порядке, и это будет так (и не то, чтобы я не исправил вашу инициализацию, которая только инициализировала диагональные элементы. Вы должны использовать компилятор C, а не C ++, чтобы скомпилируйте это.):

#include <stdio.h>

void print_2d_array(int arr_size, int arr[][arr_size]){
for(int i = 0; i < arr_size; ++i){
for(int j = 0; j < arr_size; ++j)
printf("%d\t", arr[i][j]);
printf("\n");
}
}

int main(){
int x[] = {10,15,20,30,40};
int arr[sizeof(x)][sizeof(x)];

// bad initialization:
for(int i = 0; i < sizeof(x); ++i)
arr[i][i] = 0;

print_2d_array(5, arr);
return 0;
}

Хорошо, если вы решили использовать C ++, но не любите vector, следующая простейшая вещь — использовать примитивные указатели, что не рекомендуется.

#include <iostream>
#include <vector>

using namespace std;

void print_2d_array(int arr_size, int **arr){
for(int i = 0; i < arr_size; ++i){
for(int j = 0; j < arr_size; ++j)
cout << arr[i][j] << "\t";
cout << endl;
}
}

int main(){
vector<int> x {10,15,20,30,40};
int **arr = new int*[x.size()];
for (int i = 0; i < x.size(); ++i) {
arr[i] = new int[x.size()];
for (int j = 0; j < x.size(); ++j) {
arr[i][j] = 0;
}
}

print_2d_array(5, arr);

for (int i = 0; i < x.size(); ++i) {
delete[] arr[i];
}
return 0;
}

Сохраните свои проблемы и используйте контейнеры. Вы используете современный C ++.

(Ответ предполагает, что вы не можете определить размер массива перед запуском. Хотя это не так в вашем примере — размер должен быть 5, и нет причин использовать VLA.)

1

Другие решения

Прежде всего,

int arr[x.size()][x.size()];

не является допустимым C ++. Размеры массива должны быть известны во время компиляции.

Если вы используете компилятор, который поддерживает массивы переменной длины, в качестве расширения, вы можете использовать этот оператор. Но тогда тип переменной не int (*)[5]что и ожидается print_2d_array,

Вы можете использовать вложенный std::array если вы знаете размеры во время компиляции.

Вы можете использовать вложенный std::vector если нужно вычислить размеры во время выполнения.

Обновление в ответ на комментарий ОП

Возьмите упрощенную версию программы.

#include <iostream>
#include <vector>

using namespace std;

int main(){
vector<int> x{10,15,20,30,40};
int arr[x.size()][x.size()];
return 0;
}

Команда для компиляции:

g++ -Wall -std=c++11    socc.cc   -o socc -pedantic

Ошибки / предупреждения:

socc.cc: In function ‘int main()’:
socc.cc:8:31: warning: ISO C++ forbids variable length array ‘arr’ [-Wvla]
int arr[x.size()][x.size()];
^
socc.cc:8:31: warning: ISO C++ forbids variable length array ‘arr’ [-Wvla]
socc.cc:8:9: warning: unused variable ‘arr’ [-Wunused-variable]
int arr[x.size()][x.size()
0

По вопросам рекламы [email protected]