Consider a data structure to describe blocks of a matrix in C:
// Matrix block
typedef struct {
union {
int i;
double d;
} *a; // pointer to first element in matrix block
int k; // block index
int p; // no. of block rows
int q; // no. of block columns
int m; // no. of matrix rows
int n; // no. of matrix columns
int r; // MPI rank of block owner
} mtrx_blk;
I would like to use a union for the pointer to the first element of a matrix block. I would like to use the same mtrx_blk
structure for different matrix types. In my case matrices can be either of type double
or int
. For example, if I create two matrix blocks with NBLK = 2;
and a matrix A
of type double
:
// for each block
for (int k = 0; k < NBLK; k++) {
blk[k] = (mtrx_blk) { .a = &A[k*P*Q], .k = k, .p = P, .q = Q, .m = M, .n = N, .r = k };
}
Matrix A is of size M x N elements and matrix blocks are of size P x Q elements.
The above way to assign to a pointer .a
results in an error:
gcc -std=c11 -pedantic-errors struct-union.c -o struct-union
struct-union.c: In function 'main':
struct-union.c:52:36: error: initialization of 'union <anonymous> *' from incompatible pointer type 'double *' [-Wincompatible-pointer-types]
52 | blk[k] = (mtrx_blk) { .a = &A[k*P*Q], .k = k, .p = P, .q = Q, .m = M, .n = N, .r = k };
| ^
struct-union.c:52:36: note: (near initialization for '(anonymous).a')
I tried to phrase it as:
// for each block
for (int k = 0; k < NBLK; k++) {
blk[k] = (mtrx_blk) { .a.d = &A[k*P*Q], .k = k, .p = P, .q = Q, .m = M, .n = N, .r = k };
}
But this also fails to compile with
gcc -std=c11 -pedantic-errors struct-union.c -o struct-union
struct-union.c: In function 'main':
struct-union.c:52:31: error: field name not in record or union initializer
52 | blk[k] = (mtrx_blk) { .a.d = &A[k*P*Q], .k = k, .p = P, .q = Q, .m = M, .n = N, .r = k };
| ^
struct-union.c:52:31: note: (near initialization for '(anonymous)')
struct-union.c:52:38: error: initialization of 'union <anonymous> *' from incompatible pointer type 'double *' [-Wincompatible-pointer-types]
52 | blk[k] = (mtrx_blk) { .a.d = &A[k*P*Q], .k = k, .p = P, .q = Q, .m = M, .n = N, .r = k };
| ^
struct-union.c:52:38: note: (near initialization for '(anonymous).a')
My questions are:
- How do I do it correctly?
- Is my logic correct and can I use the analogous syntax
.a.i = &B[k*P*Q]
for a matrixB
of an integer data type?
Please find the full source code below:
#include <stdlib.h>
// Matrix block
typedef struct {
union {
int i;
double d;
} *a; // pointer to first element in matrix block
int k; // block index
int p; // no. of block rows
int q; // no. of block columns
int m; // no. of matrix rows
int n; // no. of matrix columns
int r; // MPI rank of block owner
} mtrx_blk;
int main(int argc, char *argv[]) {
// no. of matrix rows
int const M = 10;
// no. of matrix columns
int const N = 10;
// no. of blocks
int const NBLK = 2;
// no. of block rows
int const P = M/NBLK;
// no. of block columns
int const Q = N;
// allocate memory for matrix
double *A = (double*) malloc(M*N*sizeof(double));
// allocate array of blocks
mtrx_blk *blk = (mtrx_blk*) malloc(NBLK*sizeof(mtrx_blk));
// for each block
for (int k = 0; k < NBLK; k++) {
blk[k] = (mtrx_blk) { .a.d = &A[k*P*Q], .k = k, .p = P, .q = Q, .m = M, .n = N, .r = k };
}
// free memory of array of blocks
free(blk);
// free memory of matrix
free(A);
return 0;
}
You need to sign in to view this answers
Leave feedback about this