LINUX.ORG.RU

двумерный массив в heap на c


0

2

Здравствуйте, изучаю форматы файлов изображений, решил попробовать написать конвертер для чего-то вроде raw: http://pastebin.com/LgPxFTb8
Эта программа должна создать файл, указатель на массив int'ов в памяти, забить массив рандомными данными (0 и 1) и записать их в файл.
Указатель объявлен так:
int **img_array;

Вот выделение памяти:
img_array = (int**) malloc ( LENGTH * HEIGHT * sizeof(int) );

Потом я уже использую его как двумерный массив:
img_array[rows][cols] = rand()%2;

На этом месте программа выдает сегфолт. Скорее всего, ошибка очевидная, но с heap'ом раньше я работал только на c++, там можно было просто int x = new y
Прошу помощи, заранее спасибо

Ответ на: комментарий от ms-dos32

в C массивы начинаются с 0 -> точка (3, 2) на самом деле (2, 1) и её линейный адресс 6. если я конечно правильно понял твою проблему.

beastie ★★★★★
()
Ответ на: комментарий от schizoid

почему это? Кто тебе сказал, что память, возвращаемая malloc'ом, идёт подряд? Там разные куски могут быть на разных страницах и физически находиться по разным адресам. Только тебя это особо не должно волновать, так как с физическими адресами ты не работаешь.g

anonymous
()
Ответ на: :) от schizoid

Как ты до этого додумался?

и вот,
for(cols=0; cols<HEIGHT; cols++)
{
for(rows=0; rows<LENGTH; rows++)
{
img_array[rows+cols*LENGTH] = 1;
}
}
выводит одну длинную строку в 640 символов, а должно быть 480 строк по 640 символов. Где я ступил? :-)

ms-dos32
() автор топика
Ответ на: комментарий от ms-dos32

Как ты до этого додумался?

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

qnikst ★★★★★
()

афтар, а с чего ты решил что

img_array = (int**) malloc ( LENGTH * HEIGHT * sizeof(int) );
даст тебе двухмерный массив? пеши на Сэ правильно
img_array = (int*) malloc ( LENGTH * HEIGHT * sizeof(int) );
img_array[rows*width+cols] = rand()%2;

ckotinko ☆☆☆
()
Ответ на: комментарий от ckotinko

С ними немного по-другому нужно работать, на самом деле твой вариант - одномерный массив, он мне вроде подходит

ms-dos32
() автор топика
Ответ на: комментарий от beastie

явное приведение типов скрывает ряд ошибок

Ошибки, связанные с забытым include - это непроработаный дизайн языка, и в 99 году это было исправлено. Больше явное приведение ничего не скрывает.

и не приносит никаких преимуществ

А вот приносит. Во-первых, совместимость с C++, во-вторых, оно как раз выявит ошибки, связанные со сменой типа. Например:

p->n = malloc(sizeof(float * 10));
Теперь представь, что я сменил тип поля n с float* на double*. Строка стала неверна, но компилятор мне об этом не скажет. А если добавить явное приведение типов - скажет.

Так что не надо про попугаев, надо думать самому. Уж точно это не «bad habbit».

unsigned ★★★★
()
Ответ на: комментарий от unsigned

Во-первых, совместимость с C++, во-вторых, оно как раз выявит ошибки, связанные со сменой типа.

Совместимость с плюсами нужна для хедеров, а не для определений функций. А там дёргать malloc как-то незачем. Хотя если очень уж хочется, то каст пригодится, да. Против смены типа сгодится старая-добрая идиома

var = malloc(count * sizeof(var));

const86 ★★★★★
()
Ответ на: комментарий от unsigned

за sizeof(float * 10) надо, гммм... мягко говоря... хмммм...., кастрировать, шоб не размножались, дальше и обсуждать нечего. по-поводу C++ уже ответили выше, повторятся не буду. да и что спорить? ссылки были, энное кол-во уважаемых юзверей лора со мной согласно, да и вас, попугаев, переучивать не моё призвание.

/thread

beastie ★★★★★
()
Ответ на: комментарий от const86

Есть такая практика - сишный код плюсовым компилятором проверять, ибо тот отлавливает чуть больше ошибок. Да и переход с C на C++ без переписывания старого кода встречается нередко.

unsigned ★★★★
()
Ответ на: комментарий от beastie

ссылки были

Протухли твои ссылки 10 лет назад (да и тогда обоснование было за уши притянуто). Цитировать их не понимая - это и есть попугайство.

unsigned ★★★★
()
Ответ на: комментарий от unanimous

Ну вообще-то любой указатель вне зависимости от того, где он находится (в heap или в стеке) дает доступ к своим ячейкам по ссылке. Или я не так понял?
А создавать отдельный массив для каждой строки - это плохо, согласен

ms-dos32
() автор топика
Ответ на: комментарий от ms-dos32

Правильно многомерные массивы реализовывать, как в фортране — упаковкой по столбцам или строкам в одномерный.

unanimous ★★★★★
()
Ответ на: комментарий от Eddy_Em

Твои бенчмарки — говно. Хотя бы потому, что непонятно, обращался ли ты в правильном порядке к массиву — в Фортране, например, с его column order итерирование сначала по номеру строки, а потом столбца идет ГОРАЗДО быстрее, чем наоборот.

Но, видимо, ты об этом не в курсе.

unanimous ★★★★★
()
Ответ на: комментарий от unanimous

в Фортране, например, с его column order итерирование сначала по номеру строки, а потом столбца идет ГОРАЗДО быстрее, чем наоборот.

Ясен пень, если реализовать двумерный массив в виде одномерного, поочередно записывая строки, так и будет. А если поочередно записывать столбцы, будет наоборот.

Eddy_Em ☆☆☆☆☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.