typedef fixed length array
CArraysGccTypedefC Problem Overview
I have to define a 24-bit data type.I am using char[3]
to represent the type. Can I typedef char[3]
to type24
? I tried it in a code sample. I put typedef char[3] type24;
in my header file. The compiler did not complain about it. But when I defined a function void foo(type24 val) {}
in my C file, it did complain. I would like to be able to define functions like type24_to_int32(type24 val)
instead of type24_to_int32(char value[3])
.
C Solutions
Solution 1 - C
The typedef would be
typedef char type24[3];
However, this is probably a very bad idea, because the resulting type is an array type, but users of it won't see that it's an array type. If used as a function argument, it will be passed by reference, not by value, and the sizeof
for it will then be wrong.
A better solution would be
typedef struct type24 { char x[3]; } type24;
You probably also want to be using unsigned char
instead of char
, since the latter has implementation-defined signedness.
Solution 2 - C
You want
typedef char type24[3];
C type declarations are strange that way. You put the type exactly where the variable name would go if you were declaring a variable of that type.
Solution 3 - C
From R..'s answer:
> However, this is probably a very bad idea, because the resulting type > is an array type, but users of it won't see that it's an array type. > If used as a function argument, it will be passed by reference, not by > value, and the sizeof for it will then be wrong.
Users who don't see that it's an array will most likely write something like this (which fails):
#include <stdio.h>
typedef int twoInts[2];
void print(twoInts *twoIntsPtr);
void intermediate (twoInts twoIntsAppearsByValue);
int main () {
twoInts a;
a[0] = 0;
a[1] = 1;
print(&a);
intermediate(a);
return 0;
}
void intermediate(twoInts b) {
print(&b);
}
void print(twoInts *c){
printf("%d\n%d\n", (*c)[0], (*c)[1]);
}
It will compile with the following warnings:
In function ‘intermediate’:
warning: passing argument 1 of ‘print’ from incompatible pointer type [enabled by default]
print(&b);
^
note: expected ‘int (*)[2]’ but argument is of type ‘int **’
void print(twoInts *twoIntsPtr);
^
And produces the following output:
0
1
-453308976
32767
Solution 4 - C
Arrays can't be passed as function parameters by value in C.
You can put the array in a struct:
typedef struct type24 {
char byte[3];
} type24;
and then pass that by value, but of course then it's less convenient to use: x.byte[0]
instead of x[0]
.
Your function type24_to_int32(char value[3])
actually passes by pointer, not by value. It's exactly equivalent to type24_to_int32(char *value)
, and the 3
is ignored.
If you're happy passing by pointer, you could stick with the array and do:
type24_to_int32(const type24 *value);
This will pass a pointer-to-array, not pointer-to-first-element, so you use it as:
(*value)[0]
I'm not sure that's really a gain, since if you accidentally write value[1]
then something stupid happens.
Solution 5 - C
To use the array type properly as a function argument or template parameter, make a struct instead of a typedef, then add an operator[]
to the struct so you can keep the array like functionality like so:
typedef struct type24 {
char& operator[](int i) { return byte[i]; }
char byte[3];
} type24;
type24 x;
x[2] = 'r';
char c = x[2];
Solution 6 - C
Here's a short example of why typedef array can be confusingly inconsistent. The other answers provide a workaround.
#include <stdio.h>
typedef char type24[3];
int func(type24 a) {
type24 b;
printf("sizeof(a) is %zu\n",sizeof(a));
printf("sizeof(b) is %zu\n",sizeof(b));
return 0;
}
int main(void) {
type24 a;
return func(a);
}
This produces the output
sizeof(a) is 8
sizeof(b) is 3
because type24 as a parameter is a pointer. (In C, arrays are always passed as pointers.) The gcc8 compiler will issue a warning by default, thankfully.
Solution 7 - C
Building off the accepted answer, a multi-dimensional array type, that is a fixed-length array of fixed-length arrays, can't be declared with
typedef char[M] T[N]; // wrong!
instead, the intermediate 1D array type can be declared and used as in the accepted answer:
typedef char T_t[M];
typedef T_t T[N];
or, T
can be declared in a single (arguably confusing) statement:
typedef char T[N][M];
which defines a type of N
arrays of M
chars (be careful about the order, here).