Массивы в структурах - PullRequest
       16

Массивы в структурах

1 голос
/ 22 февраля 2011

Я новичок в C и у меня проблемы с типами массивов при внедрении в структуры. Ниже приведен пример моей проблемы:

typedef struct {
    double J[151][151];
} *UserData;

static int PSolve(void *user_data, N_Vector solution)
{
UserData data;
data = (UserData) user_data;

double J[151][151];
J = data->J;

/* Solve a matrix equation that uses J, stored in 'solution' */

return(0);
}

Когда я пытаюсь скомпилировать это, я получаю ошибка: несовместимые типы при назначении типу double [151] [151] ’из типа double (*) [151]’

Мой текущий обходной путь для этого заключается в замене «J [x] [y]» на «data-> J [x] [y]» в коде для решения матричного уравнения, но профилирование показало, что это менее эффективный.

Изменение аргументов на PSolve не вариант, потому что я использую решатель sundials-cvode, который предписывает тип и порядок аргументов.

Ответы [ 4 ]

5 голосов
/ 22 февраля 2011
typedef struct {
    double J[151][151];
} UserData; // This is a new data structure and should not a pointer!

static int PSolve(void *user_data, N_Vector solution)
{
UserData* data; // This should be a pointer instead!
data = (UserData*) user_data;

double J[151][151];
memcpy(J, data->J, sizeof(double) * 151 * 151); // use memcpy() to copy the contents from one array to another

/* Solve a matrix equation that uses J, stored in 'solution' */

return(0);
}
2 голосов
/ 22 февраля 2011

Основная причина вашей проблемы заключается в том, что типы массивов не могут быть напрямую назначены в C. Вы должны явно использовать memcpy(), как показывает ответ karlphillip .

Обратите внимание, что выполнение копирования может уничтожить выгоды оптимизации, которые вы получаете в оставшейся части функции. Предположительно, аргумент solution является указателем, и оптимизатор беспокоится о возможном алиасинге между user_data / data и solution. В качестве альтернативы, если у вас есть компилятор, который поддерживает ключевое слово restrict в C99, используйте этот аргумент в аргументах:

static int PSolve(void * restrict user_data, N_Vector restrict solution)

Это обещает компилятору, что эти указатели делают , а не псевдоним, и должен позволить вам напрямую использовать data->J, не жертвуя оптимизацией компилятора.

Некоторые компиляторы делают ключевое слово restrict доступным в режиме C89 под таким написанием, как __restrict - для получения более подробной информации обратитесь к документации вашего компилятора.

0 голосов
/ 22 февраля 2011

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

То, что вам нужно в вашем коде, выглядит примерно так:

double (*J)[151] = data->J;

, который является указателем на массивы длины 151.Или, если вы хотите использовать typedefs

typedef double line[151];
line *J = data->J;

, вот и все, вам не следует копировать данные, а просто указатель на данные.

Редактировать: Но видяя думаю, что все это - чистые предположения о том, где может быть ваше узкое место.Это может быть просто где угодно, например, что вы обращаетесь к матрице «неправильно», по столбцам или как угодно.Или то, что выкачка данных из памяти просто доминирует в ваших вычислениях.

Возможно, стоит взглянуть на ассемблер, который создает ваш компилятор (опция -S), чтобы увидеть, есть ли что-то подозрительное.

0 голосов
/ 22 февраля 2011

Попробуйте определить локальную переменную double J[151][151] как double **J.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...