expected expression before '{' token - c

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 *

Related

How to initialize a constant array of struct in another dynamically allocated struct

Here is my problem, I try to initialize constant values ​​from a struct, for simple values ​​I do like this: *(int*)&myStruct->myValue = 1; and it works very well but for the array I would have liked to use a similar method more than a 'memcpy' so I did like this:
*(MyOtherStruct*)&myStruct->myArrayOfStructs = {
otherStruct1, otherStruct2,
otherStruct3, otherStruct4
};
But I get this: error: expected expression before ‘{’ token
And I tried a lot of things but either it was totally buggy, or I had other error messages, I can't find the expression that the compiler wants and that works correctly...
Afterwards maybe the use of 'memcpy' is "obligated" but I will find it better without for my code if possible.
Thanks in advance !
EDIT: Here is an abstract but "working" example of what I want to do.
#include <stdlib.h>
typedef struct {
int r, g, b, a;
} Color;
typedef struct {
const int value;
const Color color[4];
} structExample;
int main(void)
{
Color colorWhite = { 0, 0, 0, 255 };
Color colorBlack = { 255, 255, 255, 255 };
Color colorRed = { 255, 0, 0, 255 };
Color colorBlue = { 0, 0, 255, 255 };
structExample* myStruct = malloc(sizeof(structExample));
*(int*)&myStruct->value = 1;
*(Color*)&myStruct->color = {
colorWhite, colorBlack,
colorRed, colorBlue
};
return 0;
}
You cannot assign an array, nor multiple elements of an array with one assignment. You can assign the elements of the array, for which you ought to do the casting correctly:
myStruct->color is an array of 4 Color. Taking its address yields a Color (*)4. Casting that to Color * leads to technical violations of rules required for the behavior to be define by the C standard.
Your goal is to remove const from the element. So simply take the address of an element instead of taking the address of the array:
* (Color *) &myStruct->color[0] = colorWhite;
* (Color *) &myStruct->color[1] = colorBlack;
* (Color *) &myStruct->color[2] = colorRed;
* (Color *) &myStruct->color[3] = colorBlue;
However, this casting away of const makes it irksome to avoid violating rules of the C standard regarding defined behavior. A better approach is:
Remove the const from the member declarations in structExample.
Allocate memory and initialize the structure with no const involved.
Assign the pointer to the memory to a new pointer that does have const.
When you do this, you can also use a compound literal to initialize the structure (even though it contains an array). Here is an example:
#include <stdlib.h>
typedef struct
{
int r, g, b, a;
} Color;
typedef struct
{
int value;
Color color[4];
} structExample;
int main(void)
{
Color colorWhite = { 0, 0, 0, 255 };
Color colorBlack = { 255, 255, 255, 255 };
Color colorRed = { 255, 0, 0, 255 };
Color colorBlue = { 0, 0, 255, 255 };
// Start with pointer to non-const object.
structExample *myStruct = malloc(sizeof *myStruct);
// Assign initial value.
*myStruct =
(structExample) { 1, { colorWhite, colorBlack, colorRed, colorBlue } };
// Convert to pointer to const object.
const structExample *myStructConst = myStruct;
// Use pointer-to-const for further work.
extern void foo(const structExample *);
foo(myStructConst);
/* Inside foo, only the pointer-to-const is seen, so it will get a
diagnostic message if it attempts to modify the structure without
using an explicit cast. foo does not see the original myStruct
pointer.
*/
// Use the original pointer to free.
free(myStruct);
}
You cant assign the arrays. You need to do this manually
myStruct->myArrayOfStructs[0] = otherStruct1;
myStruct->myArrayOfStructs[1] = otherStruct2;
myStruct->myArrayOfStructs[2] = otherStruct3;
myStruct->myArrayOfStructs[3] = otherStruct4;

Array of struct initialization in C

I cannot find the solution to this. I can initialize an array of struct like this:
typedef struct S_A {
int x;
} T_A;
T_A ta1[3];
ta1[0] = (T_A){0};
ta1[1] = (T_A){1};
ta1[2] = (T_A){2};
T_A ta2[3] = { {0}, {1}, {2} };
But how can I do a one-line initialization after declaration?
T_A ta3[3];
ta3 = (?){ {?}, {?}, {?} };
ta3 = (T_A[3]){ { 0 }, { 1 }, { 2 } }; // error
ta3 = (T_A*) { { 0 }, { 1 }, { 2 } }; // error
Arrays are special in C. You can only once initialize arrays. You can't then "re-initialize" arrays. Assignments on arrays don't work. Array is in most contexts a pointer that you can't assign to. You can't:
int arr[3];
// arr = {1,2,3}; // will not work
// arr = anything; // will not work
You only can memcpy to them with a compound literal:
memcpy(ta3, (T_A[3]){ { 0 }, { 1 }, { 2 } }, sizeof(ta3));
Or without compund literal initialize a temporary variable and memcpy:
const T_A temp[3] = { { 0 }, { 1 }, { 2 } };
memcpy(ta3, temp, sizeof(ta3));
In C, an initialization is something that you do simultaneously as the declaration. You cannot do it afterwards.
This can be seen in the grammar that you can find here: https://www.lysator.liu.se/c/ANSI-C-grammar-y.html
Whenever you use the = after you have finished the declaration, it's an assignment and not an initialization, and assignments have different rules. One of these rules is that the common way of initializing arrays - = {1,2,3} - simply is not allowed. You have to use memcpy or something like that.
When it comes to nonarrays, like int, double etc and their pointers, it is still true that you cannot formally initialize them after declaration, but for those, assignment has the same syntax so it can be confusing.
However, there is a trick that can be used for arrays. Wrap the array in a struct and do like this:
struct wrapper{
int arr[3];
} x;
x = (struct wrapper){{1,2,3}};
Unfortunately, as others already mentioned, one cannot assign anything to an array.
int arr[N];
...
arr = ... ; // --> This will always fail compilation
The only option is such case is either to assign new value to each array entry separately
arr[i] = ...;
Or use memcpy to copy values from other memory location.
The interesting thing is that if one defines a struct of array(s) rather than an array of struct(s):
typedef struct S_S {
int x[3];
} T_S;
then the assignment after the declaration is allowed:
typedef struct S_S {
int x[3];
} T_S;
int main(void)
{
T_S y;
y = (T_S){.x = {1, 2, 3}}; //OK!
return 0;
}
This perfectly compiles (assuming your compiler supports C99 standard)!

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.

Cannot initialize an array of struct within a struct

I'm trying to create an RPG-esque inventory, my inventory contains a type 'sword' which is an array.
Here's the code for my sword struct:
typedef struct
{
char weaponName[35];
int damage;
int rarity;
float price;
} sword;
Here's the one for the inventory:
typedef struct
{
sword SwordInvent[size];
} inventory;
I tried to initialize the SwordInvent array in the main function but it ends up with an error.
[Error] expected expression before '{' token
main()
{
inventory inv;
inv.SwordInvent[0] = {"Paper Sword", 1, 1, 1};
}
Can anyone be kind enough to help me get out of this hole? :(
EDIT
I could not thank you all enough! I wasn't really expecting to get this much of help! Seriously, thank you!
You can't just start listing stuff inside braces and have the compiler magically figure out what you want. It doesn't work like that, except with initializers. Initializers, e.g.
const sword excalibur = { "Excalibur!", INT_MAX, INT_MAX, FLT_MAX };
are different from assignment. With initializers, it's assumed that the right-hand side is going to match the left-hand side, since it's an initializer. Also, they existed longbefore compound literals, so way back this was all you could to with = and structures.
Your code (assignment) is a bit like this:
float x;
x = 1 / 2;
This does not do a floating-point division, since 1 and 2 are both integers; the compiler does not figure out that this should have a floating point result based on the type of the left-hand side (and no, with an initializer for a float it still doesn't help, float x = 1 / 2; will not assign 0.5 but 0; end of analogy).
The same is true (kind of) for your brace-list assignment. There needs to be something on the right hand side that indicates the type of the braced list.
Thus, you need to use the compound literal syntax:
inv.SwordInvent[0] = (sword) {"Paper Sword",1,1,1};
Also, your sword is not an array, it's a struct.
When you write:
inventory inv;
inv.SwordInvent[0]={"Paper Sword",1,1,1};
you are not doing initialization; you are doing (attempting to do) an assignment. Initialization would look like:
inventory inv = { { "Paper Sword", 1, 1, 1 } };
Also note that this initializes all elements of the inv variable; the ones without an explicit value are zeroed.
If you want to do assignment, use a compound literal (C99 or later):
inventory inv;
inv.SwordInvent[0] = (sword){ "Paper Sword", 1, 1, 1 };
Note that after this executes, only element 0 of the array has values assigned; all the other elements are still uninitialized (have indeterminate values). So, unless size == 1, there's a fairly big difference between the initialization and the assignment.
You have to specify the type before assignment:
inv.SwordInvent[0] = (sword) { "Paper Sword", 1, 1, 1 };
You can do it at the declaration line.
The simplest way to emulate what you're trying to do is:
inventory inv = {{"Paper Sword",1,1,1}};
A more general (and perhaps readable) manner would be:
inventory inv =
{
.SwordInvent =
{
{
.weaponName = "Paper Sword",
.damage = 1,
.rarity = 1,
.price = 1
}
}
};
If you want to initialize, say, two entries in the array, then you could use something like:
inventory inv =
{
.SwordInvent =
{
{
.weaponName = "Paper Sword",
.damage = 1,
.rarity = 1,
.price = 1
},
{
.weaponName = "Light Saber",
.damage = 100,
.rarity = 100,
.price = 100
}
}
};
inv.SwordInvent[0]={"Paper Sword",1,1,1};
Such assignment is illegal. Expression at the right side of = should have proper type. The easiest way is to use compound literal (as mentioned in other answers):
inv.SwordInvent[0] = (sword){"Paper Sword",1,1,1};
Alternatively you can use next initialization:
inventory inv = {
{
{"Paper Sword",1,1,1}, /* init SwordInvent[0] */
{"Paper Sword",1,1,1}, /* init SwordInvent[1] */
/* ... */
}
};
This variant conforms to C89, that may be useful if your compiler doesn't support newest language features.

using #define for defining struct objects

I came across this simple program somewhere
#include<stdio.h>
#include<stdlib.h>
char buffer[2];
struct globals {
int value;
char type;
long tup;
};
#define G (*(struct globals*)&buffer)
int main ()
{
G.value = 233;
G.type = '*';
G.tup = 1234123;
printf("\nValue = %d\n",G.value);
printf("\ntype = %c\n",G.type);
printf("\ntup = %ld\n",G.tup);
return 0;
}
It's compiling (using gcc) and executing well and I get the following output:
Value = 233
type = *
tup = 1234123
I am not sure how the #define G statement is working.
How G is defined as an object of type struct globals ?
First, this code has undefined behavior, because it re-interprets a two-byte array as a much larger struct. Therefore, it is writing past the end of the allocated space. You could make your program valid by using the size of the struct to declare the buffer array, like this:
struct globals {
int value;
char type;
long tup;
};
char buffer[sizeof(struct globals)];
The #define is working in its usual way - by providing textual substitutions of the token G, as if you ran a search-and-replace in your favorite text editor. Preprocessor, the first stage of the C compiler, finds every entry G, and replaces it with (*(struct globals*)&buffer).
Once the preprocessor is done, the compiler sees this code:
int main ()
{
(*(struct globals*)&buffer).value = 233;
(*(struct globals*)&buffer).type = '*';
(*(struct globals*)&buffer).tup = 1234123;
printf("\nValue = %d\n",(*(struct globals*)&buffer).value);
printf("\ntype = %c\n",(*(struct globals*)&buffer).type);
printf("\ntup = %ld\n",(*(struct globals*)&buffer).tup);
return 0;
}
The macro simply casts the address of the 2-character buffer buf into a pointer to the appropriate structure type, then de-references that to produce a struct-typed lvalue. That's why the dot (.) struct-access operator works on G.
No idea why anyone would do this. I would think it much cleaner to convert to/from the character array when that is needed (which is "never" in the example code, but presumably it's used somewhere in the larger original code base), or use a union to get rid of the macro.
union {
struct {
int value;
/* ... */
} s;
char c[2];
} G;
G.s.value = 233; /* and so on */
is both cleaner and clearer. Note that the char array is too small.

Resources