Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.117.186.92] |
|
Сообщ.
#1
,
|
|
|
Добрый день!
Есть кусок чужой библиотеки, которую хочу скомпилировать под VS. Сломал уже всю голову. Проблемный код: typedef real Grid[NBINS]; #define Array(type, var, n1, n2) type (*var)[n2] = alloca((n1)*(n2)*sizeof(type)) // Видимо это эквивалентно Array(type, var, n1, n2) type var[n1][n2] Array(Grid, margsum, NCOMP, NDIM); // Так компилируется: Array(Grid, margsum, NCOMP, 3/*NDIM*/); Проблема в том, что NDIM не константа и VS ругается. Пробовал выделять память динамически: Grid ***margsum = malloc(NCOMP * NDIM * NBINS * sizeof(real)); Этот вариант компилируется, но программа падает на строке: Grid *m = &margsum[0][0]; ... m[dim][bin[dim]] += wfun; <- ТУТ Подскажите, пожалуйста, как корректно выделить память динамически. Заранее благодарен. |
Сообщ.
#2
,
|
|
|
Цитата SGregory @ Этот (библиотечный) код использует C99. У тебя какой язык? На Плюсах это проще вообще не так делать.Проблема в том, что NDIM не константа и VS ругается Цитата SGregory @ Естественно. Эта структура данных неэквивалентна исходной. Массив указателей далеко не то же самое, что массив массивов. Первый хранит указатели, и sizeof(*margsum) будет равен размеру указателя; второй хранит массивы, и соответственно sizeof(*margsum) будет равен размеру массива. Вся адресная арифметика меняется, потому [] индексируют чушь. Пробовал выделять память динамически: Grid ***margsum = malloc(NCOMP * NDIM * NBINS * sizeof(real)); Этот вариант компилируется, но программа падает на строке: ... Добавлено Тебе что конкретно надо? Если сохранить исходный формат данных, то это одно, если это не обязательно, то проще иначе. |
Сообщ.
#3
,
|
|
|
Qraizer, дело в том что библиотека не моя, поэтому сильно корежить очень не хочется, понимаю прекрасно, что через new/delete существенно проще.
Нужно путем минимальных изменений заставить работать Т.е. идеально сохранить исходный формат данных. Буду благодарен, если поможете |
Сообщ.
#4
,
|
|
|
Цитата SGregory @ Подскажите, пожалуйста, как корректно выделить память динамически. Заранее благодарен. Если у тебя грид, то тебе надо выделить массив указателей, а затем каждый указатель инициализировать уже массивом (не указателем) нужной длины. MyElement **p = new MyElement*[X]; p[0] = new MyElement[Y]; p[1] = new MyElement[Y]; и в обратном порядке правильно удалить из памяти. Это если тебе матрицу надо. |
Сообщ.
#5
,
|
|
|
ter_nk_, спасибо. Но мне необходим С код, т.к. библиотека написана на чистом С и влезать в ее внутренности не хочется.
|
Сообщ.
#6
,
|
|
|
Ты в библиотечную функцию подсовываешь указатель на выделенную память, сделано это с помощью библиотечной функции или нет, ей же не важно, ей нужны ячейки памяти данные писать. Если ты используешь VS то ты должен работать с памятью с помощью С++ функций, это new delete, а malloc это С. Сами new delete реализованны с помощью malloc и т.д. Не нужно думать об этом.
|
Сообщ.
#7
,
|
|
|
ter_nk_, нет совсем так, это внутренность библиотеки. Она не адаптирована под VS, я ее пытаюсь заставить работать.
|
Сообщ.
#9
,
|
|
|
Цитата ter_nk_ @ В VS это так, но в общем случае это необязательно.Сами new delete реализованны с помощью malloc и т.д. SGregory, самый топорный вариант описал ter_nk_: Grid ***margsum = malloc(n1 * sizeof(*margsum)); int i, j; for (i=0; i<n1; ++i) { margsum[i] = malloc(n2 * sizeof(**margsum)); for (j=0; j<n2; ++j) margsum[i][j] = malloc(NBINS * sizeof(***margsum)); } /* ... */ for (i=0; i<n1; ++i) { for (j=0; j<n2; ++j) free(margsum[i][j]); free(margsum[i]); } free(margsum); |
Сообщ.
#10
,
|
|
|
Спасибо! Попробую уже завтра. О результатах напишу.
|
Сообщ.
#11
,
|
|
|
P.S. Исходную структуру данных в C90 при переменном n2 сохранить сложно, т.к. это означает, что чтобы сохранить статичность массива, нужно каждый раз объявлять новый тип этого статического массива, зависящего от размера n2. Ведь
int a1[123]; int a2[321]; |
Сообщ.
#12
,
|
|
|
Qraizer, действительно, не работает, хотя компилирует.
Видимо придется разбираться со внутренностями библиотеки. В любом случае спасибо! |
Сообщ.
#13
,
|
|
|
Цитата Qraizer @ P.S. Исходную структуру данных в C90 при переменном n2 сохранить сложно Да и вообще, для таких вещей, как мне кажется, было бы проще делать всё указателями. Что то на вроде: typedef struct Array { void **array; int sizeX; int sizeY; } Array; ну, соответственно, выделение: Array *Arrays_Create(int sizeItem, int x, int y){ Array *array = (Array*)malloc(sizeof(Array)); array->array = malloc(sizeof(void**)); int i1; int i2; for(i1=0;i1<y;i1++) { array->array[i1] = (void*)malloc(sizeof(void*)); for(i2=0;i2<x;i2++){ array->array[i1][i2] = (void*)malloc(sizeItem); } } array->sizeX=x; array->sizeY=y; return array; } void Arrays_Delete(Array* array){ int i1; int i2; for(i1=array->sizeY-1;i1>=0;i1--){ for(i2=array->sizeX-1;i2>=0;i2--){ free(array[i1][i2]) } free(array->array[i1]); } free(array); } В старых сях, во многих местах подобное использовалось. Вся ответственность за соответствия типов целиком и полностью ложиться на вас, зато, получаете довольно мощный (для сей старого стандарта) набор функциональности. Используя массивы в стеке вы делаете оптимизацию, за которую и платите совместимостью. У меня даже остались образцы кроссплатформенных велописедов-коллекций на старых сях |
Сообщ.
#14
,
|
|
|
Цитата SGregory @ Значит действительно ей важно, чтобы весь массив лежал одним линейным регионом. Это тоже можно, как у тебя вначале было одним malloc()-ом, только тип нужно просто *margsum. Но индексировать придётся иначе – считать вручную. Можно написать макрос, который будет переводить n1, n2 и NBINS в индекс в этом линейном векторе. Можно соорудить себе вспомогательный массивы указателей на начала каждого второго и третьего измерений. Qraizer, действительно, не работает, хотя компилирует. Видимо придется разбираться со внутренностями библиотеки. |