0

I have the following C header file:

#ifndef __MATRIX_H__
#define __MATRIX_H__

struct matrix_t
{
    uint8_t col1;
    uint8_t col2;
    uint8_t col3;
};

extern const struct matrix_t matrix_a[3];
extern const struct matrix_t matrix_b[3];
extern const struct matrix_t matrix_c[3];

#define MATRIX_A_COL_1(row) matrix_a[row].col1
#define MATRIX_A_COL_2(row) matrix_a[row].col2
#define MATRIX_A_COL_3(row) matrix_a[row].col3

#define MATRIX_B_COL_1(row) matrix_b[row].col1
#define MATRIX_B_COL_2(row) matrix_b[row].col2
#define MATRIX_B_COL_3(row) matrix_b[row].col3

#define MATRIX_C_COL_1(row) matrix_c[row].col1
#define MATRIX_C_COL_2(row) matrix_c[row].col2
#define MATRIX_C_COL_3(row) matrix_c[row].col3

#endif

And the following C file:

#include "matrix.h"

const struct matrix_t matrix_a[3] =
{
    { 1, 2, 3},
    { 4, 5, 6},
    { 7, 8, 9}
};

const struct matrix_t matrix_b[3] =
{
    { 10, 11, 12},
    { 13, 14, 15},
    { 16, 17, 18}
};

const struct matrix_t matrix_c[3] =
{
    { 19, 20, 21},
    { 22, 23, 24},
    { 25, 26, 27}
};

Note: because my original code have 10 times more fields on matrix_t, so for the sake of simplicity I created this example.

So my question here is: I will need the macros from matrix_a to be used today, but tomorrow I will need the matrix_b but they are not only 3 so I can't change everything by hand, they are several. Is it possible to make some "general" macros, instead of defining all macros and changing the code when I need to use another? And how?

Should be something like this?

...

if matrix_x == A
    #define MATRIX_X_COL_1(row) matrix_a[row].col1
    #define MATRIX_X_COL_2(row) matrix_a[row].col2
    #define MATRIX_X_COL_3(row) matrix_a[row].col3
else if matrix_x == B
    #define MATRIX_X_COL_1(row) matrix_b[row].col1
    #define MATRIX_X_COL_2(row) matrix_b[row].col2
    #define MATRIX_X_COL_3(row) matrix_b[row].col3
else if matrix_x == C
    #define MATRIX_X_COL_1(row) matrix_c[row].col1
    #define MATRIX_X_COL_2(row) matrix_c[row].col2
    #define MATRIX_X_COL_3(row) matrix_c[row].col3

...

Is something like this possible to do?

Thank you.

Best regards, Ricardo Neves.

  • 12
    What's the point of any of these macros? What does writing `MATRIX_A_COL_1(row)` give you that writing `matrix_a[row].col1` does not? Beyond obfuscation. This "problem" is artficial. – Asteroids With Wings Dec 21 '20 at 18:56
  • 1
    Did you consider making an array or map of matrices? Then you can perform lookup into them with a simple variable. – Asteroids With Wings Dec 21 '20 at 18:59
  • I don't think you want to do this because the code would need to be edited and recompiled when the matrix changes. The nature of a macro is such that it changes the source code prior to compilation. – nicomp Dec 21 '20 at 18:59
  • 2
    Better to use a 2D array for a matrix, then you can apply algorithms knowing the rows and columns – Weather Vane Dec 21 '20 at 18:59
  • 3
    Please don't define your own symbols with leading double underscore (like `__MATRIX_H__`) as such symbols are reserved. See [this question and its answers](https://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier) for more information. – Some programmer dude Dec 21 '20 at 19:04
  • @WeatherVane now I see what can be done, Thank you, will try that – Ricardo Neves Dec 21 '20 at 19:05
  • @AsteroidsWithWings I will try that, I think that's what I need is to create a way to look up into an array of matrices – Ricardo Neves Dec 21 '20 at 19:08

1 Answers1

0

C preprocessors are able to understand constant literals like 1, 2, and such. Preprocessors do not have the understanding of variable references, so you cannot compare variables in a preprocessor directive.

/* comparison of constant literals is supported */
# if (1) == (1)
#endif
int x = 1;

/* C preprocessors cannot understand variable references */
/* the preprocessor will treat x as a macro, and since it can't find x the macro,
   #if always evaluates to false. And so this will not produce the intended 
   result. */
#if x == 1
#endif

However, you can do

#if !defined(MATRIX_FOR_TODAY)
#    define MATRIX_FOR_TODAY  matrix_a
#endif

#define MATRIX_COL1(ROW) (MATRIX_FOR_TODAY[(ROW)].col1)

For example on Tuesday,

gcc -c -DMATRIX_FOR_TODAY=matrix_a -o matrix.o matrix.c

and Wednesday

gcc -c -DMATRIX_FOR_TODAY=matrix_b -o matrix.o matrix.c

and so on