Использование препроцессора для определения указателей - PullRequest
0 голосов
/ 10 марта 2019

В моей программе я выделяю пять матриц NxN, используя одно распределение. Каждый сегмент NxN double s рассматривается как отдельная матрица. Когда я впервые написал код, я определил указатели для каждой матрицы следующим образом.

#define MAX_N 1024 // could be anything
double* matricies = aligned_alloc(32, 5 * MAX_N * MAX_N * sizeof(double));
double* MA = matricies;
double* MB = matricies + MAX_N * MAX_N;
double* MC1 = matricies + 2 * MAX_N * MAX_N;
double* MC2 = matricies + 3 * MAX_N * MAX_N;
double* MC3 = matricies + 4 * MAX_N * MAX_N;

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

double* matricies = aligned_alloc(32, 5 * MAX_N * MAX_N * sizeof(double));

#define MA (matricies)
#define MB (matricies + MAX_N * MAX_N)
#define MC1 (matricies + 2 * MAX_N * MAX_N)
#define MC2 (matricies + 3 * MAX_N * MAX_N)
#define MC3 (matricies + 4 * MAX_N * MAX_N)

Эти идентификаторы используются в качестве указателей в остальной части программы. Мой вопрос, является ли это хорошей практикой? У меня такое ощущение, что это не будет масштабироваться, потому что идентификаторы могут конфликтовать с другим текстом в исходном коде. Вы можете, конечно, #undef по мере необходимости, но это может стать неуклюжим.

Ответы [ 2 ]

2 голосов
/ 10 марта 2019

Это в первую очередь основано на мнении, будете ли вы использовать тот или иной путь.Подход "define" сэкономит немного памяти, так как вам не понадобятся переменные-указатели.Тем не менее, компилятор может оптимизировать переменные из кода, так что ... возможно, в любом случае ничего не будет сохранено.По моему мнению, подход «определяет» усложняет понимание и поддержку кода, поэтому я бы не стал использовать определения.

Важная проблема в вашем коде заключается в том, что он этого не делаетчто вы говорите, вы хотите, чтобы это было сделано.Вы говорите, что хотите использовать NxN, но ваш код не позволяет нам использовать его таким образом.Пример:

#define MAX_N 1024

int main(){
    double* matricies = aligned_alloc(32, 5 * MAX_N * MAX_N * sizeof(double));
    double* MA = matricies;
    double* MB = matricies + MAX_N * MAX_N;

    MA[0][3] = 42.1;          // error
    MB[2][1] = 123.8;         // error

    printf("%f\n", MA[0][3]); // error  
    printf("%f\n", MB[2][1]); // error  

    return 0;
}

Этот код приводит к ошибкам компилятора, таким как:

main.cpp:12:10: error: subscripted value is neither array nor pointer nor vector
     MA[0][3] = 42.1;

, поскольку MA является указателем на двойное число.Для доступа к данным с помощью MA[..][..] вам нужен другой тип для MA.Это может быть «указатель на массив double».Например:

#define MAX_N 1024

int main(){
    void* matricies = aligned_alloc(32, 5 * MAX_N * MAX_N * sizeof(double));
    double (*MA)[MAX_N] = matricies;
    double (*MB)[MAX_N] = MA + MAX_N;


    MA[0][3] = 42.1;
    MB[2][1] = 123.8;

    printf("%f\n", MA[0][3]);  
    printf("%f\n", MB[2][1]);  

    return 0;
}

Этот код компилируется без ошибок, и к матрицам NxN можно получить доступ, как и следовало ожидать.Наконец, IMO также легче читать и понимать, чем ваш первоначальный подход к определению.

1 голос
/ 10 марта 2019

действительно ли это хорошая практика?

#define MC3 (matricies + 4 * MAX_N * MAX_N) не очень хорошая идея. Код скрывает необычный подход к кодированию, что приводит к увеличению затрат на обслуживание.


Обратите внимание на проблему с 5 * MAX_N * MAX_N. Это делается с помощью int math, а индексирование массива и определение размера лучше всего выполняется с помощью size_t math. Исходный код может переполниться, если MAX_N > 21000 Рекомендовать 1) старшее умножение с sizeof(double) и 2) использовать u для констант размера, таких как #define MAX_N 1024u 3), не выполнять этот макрос трюк

...