Array of structures for PowerPC Compiler - c

I have a problem, I was asked to declare an array of structures, with one structure inside like so:
typedef struct {
int a;
int b;
int c;
}blah;
int main()
{
blah arr[1] = {{0, 0, 0}};
//...
}
Is the above initialization correct?

Yes, it's totally correct.
Array of length 1 is not much different from those containing multiple elements: they all are aggregate types and their initialization should be enclosed in curly braces. If your array had 2 elements, the initialization would be like
blah arr[2] = { {0, 0, 0}, {0, 0, 0} };

Yes.
You don't need to specify the size if you're going to have an explicit initializer, let the compiler figure it out:
blah arr[] = { { 0, 0, 0 } };
I've also included spaces to make the nesting a bit clearer.

Related

initializing property of structure

I'm new to c, and currently making chess program.
There's the code.
#include <stdio.h>
int spider[8][2] = {{0, 1}, {1, 1}, {1, 0}, {1, -1},
{0, -1}, {-1, -1}, {1, 0}, {-1, 1}};
int jump[8][2] = {{1, 2}, {2, 1}, {2, -1}, {1, -2},
{-2, -1}, {-1, -2}, {-1, 2}, {-2, 1}};
typedef struct
{
int color;
int type;
char symbol;
int unit[8][2];
} piece;
void add_piece(piece piece, int color, int type, char symbol, int unit[8][2])
{
piece.color = color;
piece.type = type;
piece.symbol = symbol;
for(int i = 0; i < 8; i++)
{
for(int j = 0; j < 2; j++)
{
piece.unit[i][j] = unit[i][j];
}
}
}
int main(void)
{
piece wk;
add_piece(wk, 0, 0, 'K', spider);
printf("%d", wk.color);
return 0;
}
expected output : 0
console output : 8388608
I found that 8GB = 8388608KB.
What's the meaning of that output?
Is there any problem of initializing property of structure or elsewhere?
Can you see some not good habits in this code?
Remember that in C all arguments are passed by value.
That means the value of the argument in the call is copied into the functions argument value.
So in the call
add_piece(wk, 0, 0, 'K', spider);
the value (current uninitialized contents) of the structure object wk will be copied into the argument variable piece inside the add_piece function.
When you modify the local argument variable, for example through an assignment like
piece.color = color;
you only modify the local copy. The original value used in the call will not be modified.
You can solve this in two ways:
Return the structure, and assign to a variable when doing the call; Or
Emulate pass by reference by using pointers.
Option number 2 is the most common it seems, so I will show it here.
First you need to modify the function to take a pointer to the structure object:
void add_piece(piece *piece, int color, int type, char symbol, int unit[8][2])
{
...
}
Then you need to use the "pointer to structure" syntax using the "arrow" to access structure members:
piece->color = color;
piece->type = type;
// And so on for all access to piece members...
Finally, when you call the function you need to pass a pointer to the wk variable, using the "pointer to" or "address of" operator &:
add_piece(&wk, 0, 0, 'K', spider);
I described the pass by reference emulation because it's so common and because you need to learn to recognize it. For your specific case I would rather recommend that you define a new structure object in the function and return it:
piece add_piece(int color, int type, char symbol, int unit[8][2])
{
piece piece;
piece.color = color;
piece.type = type;
// And so on, much like your current function...
// Return the structure
return piece;
}
Now you can use it as such:
piece wk = add_piece(0, 0, 'K', spider);
Note that sometimes it's not possible, or desirable, to return structures like this, and you still need to emulate pass by reference. So you need to learn both ways.
Lastly a note about the output you get: Uninitialized local (non-static) variables really are uninitialized. They will have indeterminate (read: garbage) values.
Since in your current code doesn't really initialize the original wk structure object, all its members will have such indeterminate values.
Depending on type and use, using such indeterminate values could lead to undefined behavior.

How can I automatically initialize an array of structs to 0 [duplicate]

struct mystruct s[10] = {{0}};
This appears to initialize an array of structs to 0. How does the nested braces syntax work?
Any fields not specified are initialized to zero. So here you have an array of structs. You're initializing the first element of the array with a structure initializer that initializes the first element of the structure to zero. The rest of the first structure and the rest of the array elements will all be zero too. It's a nice idiom.
As shown?
Basically, you should enclose each compound type - array, structure, etc - inside its own level of braces.
Consider:
struct mystruct
{
int i;
double d;
char s[10];
int a[5];
} s[10] =
{
{ 0, 0.0, "abc", { 1, 2, 3, 4, 5 } },
{ 1, 1.0, "def", { 2, 3 } }, // Partially initialized array
{ 2, 2.0, { 'x', 'y', 'z' }, { 0 } }, // Strings are a shorthand
[9] = { 9, 99, 0, { 9, 8, 7, 6, 5 } }, // C99 - initialize row 9
};
But you can also omit braces if you insist (bad, archaic practice):
struct mystruct t[3] =
{ // You cannot avoid using these outside braces
0, 0.00, "abc", 1, 2, 3, 4, 5, // Omitted braces
1, 1.11, "bcd", 2, 3, 4, 5, 4,
2, 2.34, // Omitted values
};
Any omitted initializers are treated as zeroes.
It is not the nested braces that initializes. The outer braces are indicating that an array is being initialized:
struct mystruct s[10] = { };
Since this is an array of structures, each structures can be initialized with further braces:
struct mystruct { int x, y, z};
struct mystruct s[10] = { {0, 1, 2}, // <-- initializes s[0].x, s[0].y, s[0].z
{1, 2, 3}, // <-- initializes s[1].x, s[1].y, s[1].z
{2, 3, 4} // <-- initializes s[2].x, s[2].y, s[2].z
};
Notice that only first three elements are initialized. According to C standard the rest 7 elements must be initialized to 0. This is what happens to your code too. As xscott mentioned in his reply, everything omitted in initializer list is initialized to 0.
It's useful to note that while the inner braces are optional, the compiler will check to ensure that opening braces only appear where they ought, and that no nested item has too many initializers. Further, one may leave out some fields of a structure and have the compiler automatically zero them, even if the structure is not at the end of the array. Note that implementations vary in their efficiency of handling this; some will divide the initialization record into small pieces, while others will simply insert lots of zeroes in the code. For example, if each struct looked like:
typedef struct {
char name[8];
char more_stuff[1016];
} THINGIE;
THINGIE my_array[] = {{"Fred"},{"George"},{"Mark"}};
some compilers would generate 3K worth of const data, while others would generate three relatively-small 'const-init' records.

Can I use scalar initialization in a struct whose member is a pointer to pointer?

I have a struct with a single member. This member is actually a pointer to pointer to integer, in order to represent a 2-dimensional integer array.
Can I use scalar initialization while creating an instance of that struct?
I am trying to create a 2-dimensional array to represent a collection of pixels for an algorithm exercise.
I should represent something like this:
{
{ 0, 0, 1, 0, 0 },
{ 0, 1, 1, 1, 0 },
{ 1, 1, 1, 1, 1 }
}
In order to represent a generic abstraction of an image, I tried to create a struct with the following structure:
struct image_t
{
unsigned short int** pixels;
};
And so I try to init an instance of that by using:
int
main()
{
struct image_t image = {
{
{0, 0, 1, 0, 0},
{0, 1, 1, 1, 0},
{1, 1, 1, 1, 1},
}
};
return 0;
}
When I try to compile, the following warnings are given:
gcc -I src src/main.c -o bin/flood-fill.bin
src/main.c: In function ‘main’:
src/main.c:41:5: warning: braces around scalar initializer
{
^
src/main.c:41:5: note: (near initialization for ‘image.pixels’)
src/main.c:42:7: warning: braces around scalar initializer
{0, 1, 0},
^
src/main.c:42:7: note: (near initialization for ‘image.pixels’)
src/main.c:42:11: warning: excess elements in scalar initializer
{0, 1, 0},
^
src/main.c:42:11: note: (near initialization for ‘image.pixels’)
src/main.c:42:14: warning: excess elements in scalar initializer
{0, 1, 0},
After making some research, I realized that, as it is gonna be an image representation, each row will have the same total of columns. Due that, I can just use a single array and store everything in a single block of memory. It resolves my problem.
However, as a curious guy, I would like to know if there is any way to use scalar initialization for such cases - if so, how can I do that?
Most likely I'm missing some critical basic concept from C language, so explanations are more than welcome. I really want to understand better the way it works under the hood.
It probably isn't a good idea, but you can use compound literals to create the structure you want, like this:
struct image_t
{
unsigned short int **pixels;
};
int main(void)
{
struct image_t image =
{
(unsigned short *[]) {
(unsigned short []){ 0, 0, 1, 0, 0 },
(unsigned short []){ 0, 1, 1, 1, 0 },
(unsigned short []){ 1, 1, 1, 1, 1 },
}
};
return image.pixels[1][4];
}
Note that one of the problems with the data structure shown is that there is no information about how many rows are in the array of pointers, nor how many items are in each row (and there's no guarantee that each row is the same length as the other rows). That alone is reason enough to think that the structure is broken (badly designed, at any rate). If you added information about the rows and columns, then it could be OK.
Note that unsigned short **pixels; is not a pointer to a 2D array. It is a pointer to (an array of) pointer(s), which is quite different.

Can someone help me with this message?

I'm writing a program in C and declared the following structure:
typedef struct
{
int type[4][4];
int color;
} block;
So, I wrote the following function to initialize the variables:
void inicialize(block aux[1])
{
aux[0].type[4][4] = {
{0, 0, 0, 0},
{1, 2, 0, 2},
{3, 2, 0, 0},
{0, 0, 0, 0}
};
}
But when I compile the program, I got the following message:
C:\ncurses\tetris.c|11|error: expected expression before '{' token|
Please, I need to finalize this program. Can someone help me with this?
Thanks.
void inicialize(block aux[1]){
memcpy(aux[0].type,
(int [4][4]){
{0, 0, 0, 0},
{1, 2, 0, 2},
{3, 2, 0, 0},
{0, 0, 0, 0}
},
sizeof(aux[0].type));
}
So, I wrote the following function to initialize the variables:
No, you didn't. That's not initialization, that's an assignment, and you can't assign arrays. Either really initialize the variable, or fill the array elements one by one, or initialize an array and memcpy(), or whatever...
You are using initialization syntax in an assignment. And that's not allowed.
You could just assign the values you need to the variable. Or you could define a constant using the initialization syntax, and assign that constant to the variable.
The latter looks like this:
const int initialBlock[4][4] = { ... };
And then you can assign like this:
aux[0].type = initialBlock;
It's also a little odd that you pass an array of block of length one to your function. It would be more usual to pass the address of a single struct.

Initialize mulitdimensional C-array with 0 elements

How could I simple initialize a multidimensional C-array with 0 elements like this:
int a[2][2] = { { 0, 0 }, {0, 0} }
This should work:
int a[2][2] = {0};
EDIT This trick may work for silencing the warning:
int a[2][2] = {{0}};
Use memset:
memset(a,0,sizeof a);
Either use memset(), or make it static and just "lazy-initialize" to zero:
static int a[2][2];
Variables with static storage class are always initialized as if all all their fields were set to 0.
Use bzero to nullify it (faster than memset):
bzero(a, sizeof(a));
Simple: add a semicolon at the end:
int a[2][2] = { { 0, 0 }, {0, 0} };
And, if all the initializers really are zero and the array isn't local, you can omit the initializer altogether because 0 is the default:
int a[2][2];
People are suggesting calling memset or bzero, but those aren't relevant to the question as given.
memset(a, 0, sizeof(a))

Resources