How to set value of all structure members at once? [duplicate] - c

This question already has answers here:
Struct initialization of the C/C++ programming language?
(5 answers)
Closed 8 years ago.
How can I set structure members using a single line of code?
typedef struct {
int x;
int y;
}test;
test obj[2];
int main()
{
obj[0].x=0; //this works
obj[0].y=0; //this works
obj[0]={0,0}; //compilation error
}

Structs can be assigned to with the = operator, exactly the same way as any other value in C:
obj[0] = existing_test;
obj[1] = function_returning_test();
The above rely on struct values that have themselves come from somewhere else in the program (possibly having been initialized in multiple statements like in the question); to create a struct value in a single expression, use the object literal syntax:
obj[0] = (test){ .x = 15, .y = 17 };
obj[1] = (test){ .y = 19 };
Any fields left out of a such a literal are still present, but set to the appropriate zero value for their type, so in the above example obj[1].x is set to zero.

If you are looking to set the values to zero, the following line of code should work:
memset(&obj,0,sizeof(obj));
However, it is only going to work if you want the values initialized to zero

You can only initialize all values in your array of structs in a single line of code when the instance is created. (not including use of memset). Consider the following example:
#include <stdio.h>
typedef struct {
int x;
int y;
} test;
int main()
{
test obj[2] = { { 3, 5 }, { 4, 6 } };
int i = 0;
for (i = 0; i < 2; i++)
printf ("\n obj[%d].x = %d obj[%d].y = %d\n", i, obj[i].x, i, obj[i].y);
return 0;
}
output:
obj[0].x = 3 obj[0].y = 5
obj[1].x = 4 obj[1].y = 6
Note: normal initialization is to 0, but different values were used to illustrate the point.

I don't think you can assign a structure value to a structure variable. Think of obj[0] is some address of memory.
But you can do it during array of structure initialization:
test obj[2] = {{0, 0}, {1, 1}};

Related

Why error: expected expression before '{' token happen when i try to initialize a struct variable [duplicate]

This question already has an answer here:
How to declare at beginning of program
(1 answer)
Closed 4 years ago.
Here is the code I used when i try to initialize the struct L:
typedef struct {
int data[20];
int length;
} SqList;
SqList L;
L = {
{1,2,3,4,5},
5
};
You are not initializing but assigning, because declaration of L and assigning a value are two separate statements in your code.
Write
SqList L = {
{1,2,3,4,5},
5
};
and it should work.
You can overwrite this initial value later, but note that you need to assign an SqList-object then, and the assignment must happen in the context of a function:
int main() {
L = (SqList){ {1,2,3,4,5}, 5 };
}

First Element of array not empty, pointer dereference

i am writing code for a microcontroller.
I have the following example so far:
// weekly table[timeslot][day]
const int _rows = 7;
const int _cols = 12;
const int _num_weekly_table = _rows * _cols;
uint32_t weekly_table[_rows][_cols];
// pointer pointing start of array weekly array
uint32_t *ptr_weekly_table = &weekly_table[0][0];
int progress_weekly_table = 0;
bool weekly_table_full = false;
/*
* according to progress_weekly_table save a value in the weekly_table
*/
void append_weekly_table( uint32_t value)
{
//insert element
printf(*ptr_weekly_table);
*(ptr_weekly_table + progress_weekly_table) = value;
//increase progress
progress_weekly_table++;
//if the table is full set flag
if (progress_weekly_table > _num_weekly_table) {
weekly_table_full = true;
}
}
During the main loop I run this line:
append_weekly_table(1);
But the resulting array does not have a 1 as the first element, instead a 3200171746 (reproducable).All other elements in the array are 1 if i continue to run append_weekly_array.
What is my error here? Quite new to pointers so I don't know if this is the issue.
For starters these declarations
const int _num_weekly_table = _rows * _cols;
uint32_t weekly_table[_rows][_cols];
are invalid if they are declarations in the global namespace because 1) you may not initialize a variable with the static storage duration with a non-constant expression and 2) you may not declare Variable Length Arrays with the static storage duration.
It seems you are compiling your program as a C++ program instead of as a C program.
In any case the function append_weekly_table is invalid.
For example this statement
printf(*ptr_weekly_table);
does not make sense because the first parameter of the function has type const char *.
int printf(const char * restrict format, ...);
^^^^^^^^^^^^
And initially the object *ptr_weekly_table has inderterminate value (if the program is a C program and the array does not have the static storage duration; otherwise the object is zero initialized).
Also this condition
if (progress_weekly_table > _num_weekly_table) {
weekly_table_full = true;
}
also is wrong. It should be written like
if (progress_weekly_table == _num_weekly_table) {
weekly_table_full = true;
}
If you want to compile your program as a C program then the variables _rows and _cols must be declared at least like
enum { _rows = 7, _cols = 12 };
Also it is a bad idea to use leading underscores in variable names because such names are reserved by the system.
Here is a demonstrative C program that can compile.
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
enum { _rows = 7, _cols = 12 };
const int _num_weekly_table = _rows * _cols;
uint32_t weekly_table[_rows][_cols];
// pointer pointing start of array weekly array
uint32_t *ptr_weekly_table = &weekly_table[0][0];
int progress_weekly_table = 0;
bool weekly_table_full = false;
void append_weekly_table( uint32_t value)
{
*(ptr_weekly_table + progress_weekly_table) = value;
//increase progress
progress_weekly_table++;
//if the table is full set flag
if (progress_weekly_table == _num_weekly_table) {
weekly_table_full = true;
}
}
int main(void)
{
append_weekly_table( 1 );
printf( "ptr_weekly_table[0] = %d\n", *ptr_weekly_table );
return 0;
}
The program output is
ptr_weekly_table[0] = 1
You could substitute these two statements
*(ptr_weekly_table + progress_weekly_table) = value;
//increase progress
progress_weekly_table++;
//if the table is full set
with one statement
ptr_weekly_table[progress_weekly_table++] = value;
The main problem is most likely this this:
printf(*ptr_weekly_table);
The expression *ptr_weekly_table an uint32_t value. Not a string (char *) which printf expects. Because you in effect pass a null pointer (since ptr_weekly_table[0] is supposedly zero) then you will ask printf to print whatever "string" is at location zero, and that will lead to undefined behavior.
To print the correct value use something like
printf("%"PRIu32"\n", ptr_weekly_table[0]);
See e.g. this format specifier macro reference for information about PRIu32.
And as you can see I used ptr_weekly_table[0] to get the first value of the array. The expressions ptr_weekly_table[0] and *ptr_weekly_table are equal.
In fact, for any pointer or array p and index i, the expression p[i] is exactly equal to *(p + i). Which means *(ptr_weekly_table + progress_weekly_table) could be written ptr_weekly_table[progress_weekly_table] (which is a couple of characters less to write, as well as often more readable).

C - declare and init array inside struct

language: C
i am trying to declare and initialize an array inside a struct and pass it to a pointer, which is itself declared in the struct xD
yes, i know my attempt is... let's say "not correct" :D
but it would be very useful if something similar would exist.
any ideas?
struct structname {
int* section_A;
int* section_B;
};
static const struct structname structvariable_a = {
.section_A = (int[]) {
[0x01] = 1,
[0x02] = 2,
[0x03] = 3
},
.section_B = (int[]) {
[0x33] = 4,
[0x34] = 5
},
};
static const struct structname structvariable_b = {
.section_A = (int[]) {
[0x01] = 10,
[0x02] = 20,
[0x03] = 30
},
.section_B = (int[]) {
[0x33] = 7,
[0x34] = 8
},
};
later, i want to access the values ...
int main()
{
struct structname* structvariablepointer;
if(foo == 1){
structvariablepointer = &structvariable_a;
} else {
structvariablepointer = &structvariable_b;
}
printf("%i", ARRAY_SIZE(structvariablepointer->section_A)); // ARRAY_SIZE(arr) equals sizeof(arr) / sizeof(arr[0]));
int b = 2;
printf("%i", structvariablepointer->section_A[b]);
}
the only error is
./include/linux/build_bug.h:29:45: Fehler: Negative Breite in Bitfeld »<anonym>«
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:(-!!(e)); }))
^
./include/linux/compiler-gcc.h:64:28: Anmerkung: bei Substitution des Makros »BUILD_BUG_ON_ZERO«
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
^~~~~~~~~~~~~~~~~
./include/linux/kernel.h:60:59: Anmerkung: bei Substitution des Makros »__must_be_array«
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
^~~~~~~~~~~~~~~
Once you take a pointer to the first element of an array, you can no longer find the size of the array through that pointer. So you will also need to make variables to hold the array size. (Or use a sentinel value for the end of the array).
One way to solve your problem would be through ugly macros:
#include <stddef.h>
#define ARRAY_SIZE(a) ( (sizeof(a)) / sizeof((a)[0]) )
struct structname {
int* section_A;
size_t A_len;
int* section_B;
size_t B_len;
};
#define A_INIT (int[]) { 0, 1, 2, 3 }
#define B_INIT (int[]) { [0x33] = 1, [0x34] = 2 }
static const struct structname structvariable_a =
{
.section_A = A_INIT,
.A_len = ARRAY_SIZE(A_INIT),
.section_B = B_INIT,
.B_len = ARRAY_SIZE(B_INIT)
};
#undef A_INIT
#undef B_INIT
It would also be possible to define static named int arrays and then use that array's name in the initializers for structvariable_a.
Consider using int const * and int const[] respectively, if you don't intend to change the contents of the arrays at runtime. Note that if this code is in a header, each translation unit will have their own copy of the arrays.
Update (as suggested by comment): using a sentinel value would look like:
struct structname {
int* section_A;
int* section_B;
};
static const struct structname structvariable_a =
{
.section_A = (int[]) { 0, 1, 2, 3, INT_MAX },
.section_B = (int[]) { [0x33] = 1, [0x34] = 2, INT_MAX }
};
and the in main or whatever, you look for INT_MAX to know where the end of the array is, e.g.:
size_t a_len;
for (a_len = 0; structvariable_a.section_A[a_len] != INT_MAX; ++a_len) { }
Obviously this means the range of valid data for the array needs to exclude the sentinel value.
The error you're getting is because ARRAY_SIZE expects an array, and structvariablepointer->section_A is not an array but a pointer.
Since your structs effectively have fixed size arrays, just declare them as arrays instead of pointers:
struct structname {
int section_A[4];
int section_B[0x35];
};
Then initialize like this:
static const struct structname structvariable_a = {
.section_A = {
[0x01] = 1,
[0x02] = 2,
[0x03] = 3
},
.section_B = {
[0x33] = 4,
[0x34] = 5
},
};
i am trying to declare and initialize an array inside a struct and pass it to a pointer, which is itself declared in the struct xD
That doesn't make any sense whatever, but your actual code is almost completely correct in C99 and later. In particular, this:
(int[]) {
[0x01] = 1,
[0x02] = 2,
[0x03] = 3
}
Is neither a declaration of nor (quite) an initialization of an array; rather, it is a compound literal of type array of int. Because arrays decay to pointers in the context given, as in most, such a compound literal can indeed be used to initialize a structure member of type int * (to point to the first element of the array). Having successfully initialized those two struct structname objects, you can certainly obtain their addresses and record those in variables.
HOWEVER, a pointer to an array element does not carry information about the number of elements in the array. If that's all you have, as is the case in your main() function, then you cannot determine the number of array elements from it. You need to be able to determine that from the content (this is why C strings must be null-terminated), or you must have that information from some other source, such as a function argument, a variable, or clairvoyance.
yes, i know my attempt is... let's say "not correct" :D but it would be very useful if something similar would exist.
If you declare the members of struct structname to be bona fide arrays then you can access and use their declared lengths. If you prefer, you can store the number of array elements in additional members of that struct. Both of those approaches are used in the wild, as are approaches based on the contents of the pointed to elements. But I don't foresee C ever gaining a facility for making your ARRAY_SIZE() macro work with pointers as it seems you would like.

C - How to initialise array of structures when the array size is large? [duplicate]

This question already has answers here:
c structure array initializing
(5 answers)
Closed 7 years ago.
Say I have a structure:
struct foo{
int field_1;
int field_2;
};
And say have an array:
foo bar[1000];
I understand that you can initialise arrays like this:
foo bar[]={
{ .field_1= 10, field_2 = 20 },
{ .field_1= 30, field_2 = 40 },
};
This is not practical at all when the array has 1000 elements. I need to initialise all elements to a specific integer (at compile time) but it looks like it is not practically possible to do this unless the array is very small. It seems like an essential thing to be able to do but I can't find a solution.
Thanks.
You can initialize a struct using a for loop like this -
#include<stdio.h>
struct foo{
int field_1;
int field_2;
};
int main(){
int i;
struct foo bar[1000];
for(i=0; i<1000; i++){
bar[i].field_1 = i;
bar[i].field_2 = 2*i;
}
for(i=0; i<1000; i++){
printf("bar[%d]:: field_1: %d field_2: %d\n", i, bar[i].field_1, bar[i].field_2);
}
return 0;
}
You can simply create a special "generator" program, which outputs desired C source code for an array with 1000+ initialized elements.
Run a script in your favorite language (e.g., Python), which writes this array into a header file:
fileDesc = open('MyArray.h','wt')
fileDesc.write('#define MY_ARRAY \\\n{ \\\n')
for n in range(0,1000):
fileDesc.write('\t{.field_1 = ' + '%5d'%(10+20*n) +
' , .field_2 = ' + '%5d'%(20+20*n) + '}, \\\n')
fileDesc.write('}\n')
fileDesc.close()
Then, in the source file, simply include the auto-generated header file and initialize the array:
#include "MyArray.h"
...
foo bar[] = MY_ARRAY;

expected expression before '{' token

I am getting: "error: expected expression before '{' token" for the line I've commented before. If the struct is already defined why would it need a "{" before token. Thanks for any help you can provide.
struct sdram_timing {
u32 wrdtr;
u32 clktr;
};
int calibration(void);
unsigned char read_i2c_cal(void);
static unsigned int eepcal[15];
main() {
DQS_autocalibration();
}
int calibration(void)
{
struct sdram_timing scan_list[30];
read_i2c_cal();
if(eepcal[0] == 0){
scan_list = {{eepcal[1], eepcal[2]}, {-1, -1}}; // <-- PROBLEM LINE
}
else {
//foo
}
return 0;
}
unsigned char read_i2c_cal(void) {
eepcal[0] = 0;
eepcal[1] = 02;
eepcal[2] = 03;
}
The error is because you can't assign an array that way, that only works to initialize it.
int arr[4] = {0}; // this works
int arr2[4];
arr2 = {0};// this doesn't and will cause an error
arr2[0] = 0; // that's OK
memset(arr2, 0, 4*sizeof(int)); // that is too
So applying this to your specific example:
struct sdram_timing scan_list[30];
scan_list[0].wrdtr = 0;
scan_list[0].clktr = 0;
or you could use memset the same way, but instead of sizeof(int) you need size of your structure. That doesn't always work... but given your structure, it will.
Arrays in C language are not assignable. You can't assign anything to the entire array, regardless of what syntax you use. In other words, this
scan_list = { { eepcal[1], eepcal[2] }, {-1, -1} };
is not possible.
In C89/90 you'd have to spell out your assignments line by line
scan_list[0].wrdtr = eepcal[1];
scan_list[0].clktr = eepcal[2];
scan_list[1].wrdtr = -1;
scan_list[1].clktr = -1;
In modern C (post-C99) you can use compound literals to assign entire structs
scan_list[0] = (struct sdram_timing) { eepcal[1], eepcal[2] };
scan_list[1] = (struct sdram_timing) { -1, -1 };
Finally, in modern C you can use memcpy and compound literals to copy data to the array
memcpy(scan_list, (struct sdram_timing[]) { { eepcal[1], eepcal[2] }, {-1, -1} },
2 * sizeof *scan_list);
The last variant, albeit not very elegant, is the closest way to "emulate" array assignment.
You can only use an initializer list in the declaration of the variable, not after the fact.
Initializer list can only be used to initialize an array. You cannot use it afterwards.
However if you use GCC, you can use Compound Literal extension:
scan_list = (struct sdram_timing[30]){{eepcal[1], eepcal[2]}, {-1, -1}};
You might need to change scan_list type to be struct sdram_timing *

Resources