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.
How can I create an array so that I can pass it as a pointer to this function?
void SomeFunction(double *a, double *b, double *c);
I made my 2d arrays like so (but I have errors):
static double matrix_a [MATRIX_DIM][MATRIX_DIM];
static double matrix_b [MATRIX_DIM][MATRIX_DIM];
static double matrix_c [MATRIX_DIM][MATRIX_DIM];
for (i=0;i<MATRIX_DIM;i++) {
for (j=0;j<MATRIX_DIM;j++) {
// initializing matrices here
}
}
Now I make pointers to the arrays:
double *a = &matrix_a;
double *b = &matrix_b;
double *c = &matrix_c;
And then call the function:
SomeFunction(a, b, c);
However I get the following error:
cannons.c: In function ‘main’:
cannons.c:29:14: warning: initialization from incompatible pointer type [enabled by default]
double *a = &matrix_a;
^
cannons.c:30:14: warning: initialization from incompatible pointer type [enabled by default]
double *b = &matrix_b;
^
cannons.c:31:14: warning: initialization from incompatible pointer type [enabled by default]
double *c = &matrix_c;
^
Why ?
double * means "pointer to a single double". However you have an array whose elements are arrays of double. So you in fact want a pointer to an array of double:
double (*a)[MATRIX_DIM] = &matrix_a[0]; // or matrix_a
when you access it as a[1][2] = 5.0;. Alternatively you could point to the entire array at once:
double (*x)[MATRIX_DIM][MATRIX_DIM] = &matrix_a;
but then you need an extra level of indirection to access it: (*x)[1][2] = 5.0;
You will need to use the same declaration in the parameter list too.
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
In the following code a array is initialized with s "seed" variable, which is clearly not constant expression (as it's evaluated "run-time"):
#include <stdio.h>
int main(void)
{
int s = 1, i;
int a[] = {s, s + 2, s + 4, s + 6, s + 8};
for (i = 0; i < (int) (sizeof a / sizeof a[0]); i++)
printf("%d ", a[i]); /* prints: 1 3 5 7 9 */
putchar('\n');
return 0;
}
It compiles in gcc -Wall -Wextra with no warnings. However adding -pedantic provokes:
check.c: In function ‘main’:
check.c:8: warning: initializer element is not computable at load time
check.c:8: warning: initializer element is not computable at load time
check.c:8: warning: initializer element is not computable at load time
check.c:8: warning: initializer element is not computable at load time
check.c:8: warning: initializer element is not computable at load time
Does C require constant expression for initializer elements ?
This is valid in c99 but not valid in c89 (emphasize mine):
(C89, 6.5.7) "All the expression in an initializer for an object that has static storage duration or in an initializer list for an object that has aggregate or union type shall be constant expressions"
but
(C99, 6.7.8p4) "All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals."
By default, gcc compiles with -std=gnu89 which is c89 + GNU extensions.
In addition to ouah's excellent answer I would add that C99 requires constant expression for designators within designated initializers (only in C99), e.g. following array initialization is invalid in C99:
int s = 1, i = 0;
int a[] = {[i] = s, [i+1] = s + 2, [i+2] = s + 4, s + 6, s + 8};
which might be rewritten as e.g.:
#define I 0
int s = 1, i;
int a[] = {[I] = s, [I+1] = s + 2, [I+2] = s + 4, s + 6, s + 8};
Suppose that I have an array of pointers:
char *names[] = { "Za" , "John"};
Can I declare it like this:(?)
char **names = { "Za" , "John" }
The reason I am trying to do this is that I am trying to increment the array to print its contents such that I can do:
printf("%s \n" , *(++names))
So I can get printf to print "John".
I tried the declaration char **names and I got the following warning upon compilation:
test.c: In function ‘main’:
test.c:6:2: warning: initialization from incompatible pointer type [enabled by default]
char **names = { "Za" , "John"};
^
test.c:6:2: warning: (near initialization for ‘names’) [enabled by default]
test.c:6:2: warning: excess elements in scalar initializer [enabled by default]
test.c:6:2: warning: (near initialization for ‘names’) [enabled by default]
P.S my C file name is test.c
Thanks.
Just do char **pCurrentName = names;, then you'll be able to do printf("%s \n" , *(++pCurrentName)).