Struct initialization with char array outside a function - c

I have following typedef struct:
typedef struct
{
E_Menus Menu; // E_Menus is a typedef enum
char *MenuStr[200];
int CurrentItem;
int ItemAmount;
int ItemGap;
int StartItemGap;
} T_Menu;
I want to initialize a struct of type T_Menu as a module variable (not local inside a function) as following:
char mBootMenuStr[] = {"some text"};
T_Menu mBootMenu = {eUI_BootMenu, mBootMenuStr, 1, 2, 1, 2};
But MenuStr makes me struggle. I get 2 warnings:
1 initialization of 'char *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
2 missing braces around initializer [-Wmissing-braces]
MenuStr should be a string with size 200 -> Means, the string has 200 chars.
When I remove MenuStr it builds without warnings.
What did I miss? Is it impossible to do this outside a function?
Reproducable example:
typedef enum
{
eUI_BootMenu,
eUI_LoginMenu,
eUI_HomeMenu,
} E_Menus;
typedef struct
{
E_Menus Menu;
char *MenuStr[200];
int CurrentItem;
int ItemAmount;
int ItemGap;
int StartItemGap;
} T_Menu;
char mBootMenuStr[] = {"some text"};
T_Menu mBootMenu = {eUI_BootMenu, mBootMenuStr, 1, 2, 1, 2};
Thanks for help in advance.

char *MenuStr[200]; is an array of 200 pointer-to-char.
The initializer in
T_Menu mBootMenu = {eUI_BootMenu, mBootMenuStr, 1, 2, 1, 2};
is treating mBootMenuStr and each expression after it as elements to initialize that array. The integer values of 1 and 2 are being used to initialize elements of type char *, hence the warning.
GCC gives a more detailed diagnostic:
ex.c:21:49: warning: initialization of ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
21 | T_Menu mBootMenu = {eUI_BootMenu, mBootMenuStr, 1, 2, 1, 2};
| ^
ex.c:21:49: note: (near initialization for ‘mBootMenu.MenuStr[1]’)
ex.c:21:52: warning: initialization of ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
21 | T_Menu mBootMenu = {eUI_BootMenu, mBootMenuStr, 1, 2, 1, 2};
| ^
ex.c:21:52: note: (near initialization for ‘mBootMenu.MenuStr[2]’)
ex.c:21:55: warning: initialization of ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
21 | T_Menu mBootMenu = {eUI_BootMenu, mBootMenuStr, 1, 2, 1, 2};
| ^
ex.c:21:55: note: (near initialization for ‘mBootMenu.MenuStr[3]’)
ex.c:21:58: warning: initialization of ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
21 | T_Menu mBootMenu = {eUI_BootMenu, mBootMenuStr, 1, 2, 1, 2};
This warning can be resolved by placing braces around mBootMenuStr, making it the sole initializing element for the MenuStr member of the structure:
T_Menu mBootMenu = {eUI_BootMenu, {mBootMenuStr}, 1, 2, 1, 2};
But it seems likely you simply wanted a string member, not an array of pointers, in the structure:
typedef struct
{
E_Menus Menu;
char MenuStr[200];
int CurrentItem;
int ItemAmount;
int ItemGap;
int StartItemGap;
} T_Menu;
T_Menu mBootMenu = {eUI_BootMenu, "some text", 1, 2, 1, 2};

Related

How store address of an array[] in a variable

This seems like a silly question. I have an array of chars and want to store the address of the array in another variable, but can't seem to declare the correct type for the array address (I'm using gcc):
IN:
int main(void){
char cha[] = "abcde";
char **arrayAddress = &cha;
}
OUT:
arrayaddress.c: In function ‘main’:
arrayaddress.c:3:25: warning: initialization of ‘char **’ from incompatible pointer type ‘char (*)[6]’ [-Wincompatible-pointer-types]
3 | char **arrayAddress = &cha;
| ^
This is expected, I have read elsewhere that the type of cha should be char(*)[6]. But when I try to declare arrayAddress with this type, my program fails:
IN:
int main(void){
char cha[] = "abcde";
char (*)[6]arrayAddress = &cha;
}
OUT:
arrayaddress.c: In function ‘main’:
arrayaddress.c:3:10: error: expected identifier or ‘(’ before ‘)’ token
3 | char (*)[6]arrayAddress = &cha;
| ^
make: *** [<builtin>: arrayaddress] Error 1
^
How do I define arrayAddress correctly?
It is written:
char (*arrayAddress)[6] = &cha;
Notice that the name of variable gets tucked in middle of the expression.
Arrays decay to pointers.
char cha[] = "abcde";
char *p1 = cha;
char (*arrayptr)[sizeof(cha)] = &cha;
cha, &cha[0] and &cha reference the same first element of the array cha, the only difference is the type.
cha and &cha[0] has type: pointer to char
&cha has type: pointer to array of 6 char elements.
If your compiler supports typeof extension (gcc does) then you can define the pointer as:
typeof(char (*)[6]) arrayAddress = &cha;
Or even cleaner as:
typeof(char[6]) * arrayAddress = &cha;

How can I get the size of the array in an 3D matrix?

Consider the following 3D matrix
char ShapesArray[2] = {
(char[4][4]){
{ 0, 1, 0, 0 }, //I
{ 0, 1, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 1, 0, 0 }
},
(char[3][3]){
{ 0, 1, 0 }, //J
{ 0, 1, 0 },
{ 1, 1, 0 }
}
};
by using
int i = sizeof(ShapesArray[0]));
I would expect 16 as result.
But the result in this case is: 1
What am I missing here?
char ShapesArray[2] is an array of two chars. Hence the first element's size is 1. Turn on the compiler warnings:
<source>: In function 'main':
<source>:4:2: error: initialization of 'char' from 'char (*)[4]' makes integer from pointer without a cast [-Werror=int-conversion]
4 | (char[4][4]) {
| ^
<source>:4:2: note: (near initialization for 'ShapesArray[0]')
<source>:10:2: error: initialization of 'char' from 'char (*)[3]' makes integer from pointer without a cast [-Werror=int-conversion]
10 | (char[3][3]) {
| ^
<source>:10:2: note: (near initialization for 'ShapesArray[1]')
cc1: all warnings being treated as errors
Compiler returned: 1
What the compiler is saying is that you're initializing chars with char (*)[4] and char (*)[3] which is wrong. It wouldn't even compile with a C++ compiler.

pointer to a array of initialized integers

I am trying to declare a pointer to a array of initialized ints at once(gcc 5.2.0, gnu99)
This is working
int a1[] = {1, 2, 3, 4, 5};
int (*a)[] = &a1;
I tried this and it isn't
int *why = (int p[2]) {1,2};
../src/gps/gps.c:399:18: error: expected ')' before 'p'
int *why = (int p[2]) {1,2};
^
int (*b)[5]= (int(*)[5])&({11,2,3,5,6});
../src/gps/gps.c:400:31: warning: left-hand operand of comma expression has no effect [-Wunused-value]
int (*b)[5]= (int(*)[5])&({11,2,3,5,6});
^
int (*cc)[] = &{1, 2, 3, 4, 5}
../src/gps/gps.c:402:17: error: expected expression before '{' token
int (*cc)[] = &{1, 2, 3, 4, 5}
^
What I miss here?
Here's the proper way to define these:
int *why = (int [2]) {1,2};
int (*a)[5]= &((int []){11,2,3,5,6});
When you create a compound literal, you prefix it with what looks like a typecast.
The first line didn't work because you attempted to put a variable name inside of the cast, and the second line didn't work because you didn't put the cast immediately before the part in curly braces.

Initialization of multidimensional pointers with different dimensional anonym arrays inline

I am having a noob problem.
I am making tetris in c.
I want to initialize a double pointer in a struct inline for every instance.
The width of the array differs, but it is defined in another variable.
Code:
typedef struct {
char height, width;
char **shape;
} Shape;
const Shape S_shape = {2,3, (char [][3]){{0,1,1},{1,1,0}}};
const Shape Z_shape = {2,3, (char [][3]){{1,1,0},{0,1,1}}};
const Shape T_shape = {2,3, (char [][3]){{0,1,0},{1,1,1}}};
const Shape L_shape = {2,3, (char [][3]){{0,0,1},{1,1,1}}};
const Shape ML_shape = {2,3, (char [][3]){{1,0,0},{1,1,1}}};
const Shape SQ_shape = {2,2, (char [][2]){{1,1},{1,1}}};
const Shape R_shape = {1,4, (char [][4]){{1,1,1,1}}};
int main() {
return 0;
}
It does not work. Here is the gcc error code:
tetris.c:11:1: warning: initialization from incompatible pointer type [enabled by default]
const Shape S_shape = {2,3, (char [][3]){{0,1,1},{1,1,0}}};
^
tetris.c:11:1: warning: (near initialization for ‘S_shape.shape’) [enabled by default]
tetris.c:12:1: warning: initialization from incompatible pointer type [enabled by default]
const Shape Z_shape = {2,3, (char [][3]){{1,1,0},{0,1,1}}};
^
tetris.c:12:1: warning: (near initialization for ‘Z_shape.shape’) [enabled by default]
tetris.c:13:1: warning: initialization from incompatible pointer type [enabled by default]
const Shape T_shape = {2,3, (char [][3]){{0,1,0},{1,1,1}}};
^
tetris.c:13:1: warning: (near initialization for ‘T_shape.shape’) [enabled by default]
tetris.c:14:1: warning: initialization from incompatible pointer type [enabled by default]
const Shape L_shape = {2,3, (char [][3]){{0,0,1},{1,1,1}}};
^
tetris.c:14:1: warning: (near initialization for ‘L_shape.shape’) [enabled by default]
tetris.c:15:1: warning: initialization from incompatible pointer type [enabled by default]
const Shape ML_shape = {2,3, (char [][3]){{1,0,0},{1,1,1}}};
^
tetris.c:15:1: warning: (near initialization for ‘ML_shape.shape’) [enabled by default]
tetris.c:16:1: warning: initialization from incompatible pointer type [enabled by default]
const Shape SQ_shape = {2,2, (char [][2]){{1,1},{1,1}}};
^
tetris.c:16:1: warning: (near initialization for ‘SQ_shape.shape’) [enabled by default]
tetris.c:17:1: warning: initialization from incompatible pointer type [enabled by default]
const Shape R_shape = {1,4, (char [][4]){{1,1,1,1}}};
^
tetris.c:17:1: warning: (near initialization for ‘R_shape.shape’) [enabled by default]
Gcc: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
Thanks!
SOLVED
https://gcc.gnu.org/onlinedocs/gcc/Compound-Literals.html
You're missing some compound literals and using the wrong type in the one you're using. Here is a small example of what you might want:
const Shape S_shape = {
2, /* height */
2, /* width */
(char *[]) { /* Compound literals, declaring an anonymous array of `char *` with static storage duration */
(char []) {0, 1}, /* Another compound literal, declaring a static storage duration for a `char []` that will be pointed by `char *[]` */
(char []) {1, 1} /* Same as above, this one the next (and last) element of `char *[]` */
}
};
Without the comments (for readability):
const Shape S_shape = {
2,
2,
(char *[]) {
(char []) {0, 1},
(char []) {1, 1}
}
};
https://gcc.gnu.org/onlinedocs/gcc/Compound-Literals.html

Method signature in C, passing pointer on static array

I have the following arrays:
char* mask[9];
int hSobelMask[9] = {
-1, -2, -1,
0, 0, 0,
1, 2, 1};
I want to give a pointer on this array to a method like this:
int H = applyMask(&mask, &hSobelMask);
The signature of the applyMask function is the folowing:
int applyMask(char** mask[9], int* sobelMask[9]);
But I get the following compile warning:
demo.c: In function ‘customSobel’:
demo.c:232:7: warning: passing argument 1 of ‘applyMask’ from incompatible pointer type
demo.c:181:5: note: expected ‘char ***’ but argument is of type ‘char * (*)[9]’
demo.c:232:7: warning: passing argument 2 of ‘applyMask’ from incompatible pointer type
demo.c:181:5: note: expected ‘int **’ but argument is of type ‘int (*)[9]’
What does this warning mean, how do I get rid of it ?
You want to pass the pointers to these arrays? So you're probably looking for this:
int applyMask(char* (*mask)[9], int (*sobelMask)[9]);
int applyMask(char** mask, int* sobelMask);
A char * ___[9] is an array of char *, and a char * * ___[9] is an array of char * *. They're not compatible. Just change your function signature to this:
int applyMask(char** mask, int* sobelMask)
or this:
int applyMask(char* mask[], int sobelMask[])
Edited to add (after Shahbaz's comment below): Call your function like this:
int H = applyMask(mask, hSobelMask);
There's no need for those &s, since an array variable already is a pointer to the contents of the array.

Resources