2015-09-17 5 views
2

Я запускаю следующую программу на C и получаю Segmentation fault: 11.Ошибка сегментации при печати содержимого многомерного массива

#include <stdio.h> 
#include <stdlib.h> 

#define SIZE 2 

void print_array(double **arr, int size) { 
    for (int i = 0; i < size; i++) { 
     for (int j = 0; j < size; j++) { 
      printf("%f\n", arr[i][j]); 
     } 
    } 
} 

int main(int argc, char **argv) { 
    double mat[SIZE][SIZE] = {{1, 2}, {3, 4}}; 
    print_array((double **) mat, SIZE); 
} 

Не могли бы вы объяснить, почему это может произойти? Я не считаю, что мне нужно динамически выделять память для mat, так как я передаю ее в print_arrayв пределахmain() функция.

При изменении функции подписи print_array() в

void print_array(int size, double arr[size][size]) 

проблема уходит.

Все еще интересно, но ... Почему возникает ошибка сегментации при литье mat как double ** и передается в print_array()? В конце дня double arr[2][2] и double **arr с размером 2 - это то же самое, правильно?

ответ

4

Вы получаете неопределенное поведение, так как вы лжете компилятору о том, что содержит ваша память.

Формат в памяти mat - это не то же самое, что и (double **). Первый - это компактный квадрат double s, последний - указатель на указатель. Это не одно и то же.

Вы можете представить 2D как массив строк (или столбцов, если хотите) указателей, что делает работу с двойным индексированием. Но это не то же самое, что индексирование в фактический массив.

UPDATE: Я не уверен, что возможно создать сигнатуру функции для функции, которая может получить доступ к фактическому компактному массиву или к одному, представленному через указатели ... Мое предложение состояло в том, чтобы сохранить его простой и написать две различные функции для этих различных требований:

void print_matrix_compact(const double *el0, size_t size); 
void print_matrix_indirect(const double **mtx, size_t size); 

Здесь el0 является указателем на элемент 0 фактического («компактного») массива, в то время как mtx является указателем на массив указателей на одной сохраненной как массив массивов. В обоих случаях матрицы считаются квадратными, с размером size × size элементов.

+0

Теперь я понимаю, спасибо за ваш ответ. Я использую эту функцию для печати содержимого квадратных матриц, хранящихся в стеке, в функциях, а также для печати содержимого массивов, инициализированных как «double ** mat», используя вызовы malloc. Как я могу использовать одну и ту же функцию для обоих?Как я уже упоминал, изменение подписи функции печати для принятия 'arr [size] [size]', а также параметра размера сделало трюк, но я чувствую, что если бы попытался использовать эту новую функцию, для печати массивов, хранящихся как 'double **', так как они не сохраняют двойники смежно. –

+0

Фактический тип 'arr', объявленный как' double arr [size] [size] 'и переданный функции' double [] [size] '. Функции ожидают 'double *'. Вы правильно назовете его: 'print_matrix_compact (& arr [0] [0], size);' –

1

Нет, они не то же самое.

A - это непрерывный блок памяти, содержащий double, где компилятор знает, как вычислять адреса из индексов.

A double ** является указателем на блок памяти, содержащий один или несколько указателей на блоки от double.

Обращаясь к как double **, вы интерпретируете значения double в качестве указателей.

Смежные вопросы