Initializer element is not a compile-time constant c - arrays

i don't know why i am getting this error but my code do not complies and throws the error
Initializer element is not a compile-time constant here is the code
#include <math.h>
#include <stdio.h>
const float near = 0.1f;
const int fov_angle = 90;
const float far = 1000.0f;
const float width = 800.0f;
const float height = 600.0f;
const float aspect_ratio = width / height;
const float fov = (1.0f / tan(fov_angle / 2.0)); <- error
float projMat[4][4] = {
{fov * aspect_ratio, 0, 0, 0}, <- error
{0, fov, 0, 0},
{0, 0, ((far+near)/(far-near)), 1},
{0, 0, ((2*near*far)/(near-far)), 0}
};

As the error message states, the initializer for fov, which is a global variable, cannot be computed at compile time because it includes a function call. Executable code may not reside outside of any functions. projMat has a similar problem because it depends on fov.
You'll need to set the values of these variables inside of a function, probably main.

Related

Two dimensional array initilization in Mplab XC16

I have defined the two-dimensional array inside the typedef struct as,
#define MAX_STAGES_IIR 20
typedef struct {
float A[MAX_STAGES_IIR]; // Input Gain
float a[MAX_STAGES_IIR][2]; // input stage coff
float b[MAX_STAGES_IIR][3]; // output stage coff
// float B[MAX_STAGES_IIR]; // output gain
float Xdash[MAX_STAGES_IIR][2];
float iir_k[MAX_STAGES_IIR];//
float iir_r[MAX_STAGES_IIR];//
float iir_outStage[MAX_STAGES_IIR];
}IIRFilter;
When assigning values to the array use this method,
IIRFilter BpfHX_iir1;
BpfHX_iir1.A = { 0.131726 , 0.131726 , 0.12435, 1.0f }; // gain
BpfHX_iir1.a = {{-1.63410, 0.82662},{-1.87089, 0.91410},{-1.6652, 0.7513}}; // a
BpfHX_iir1.b = {{1, 0, -1},{1, 0, -1},{1, 0, -1}}; // b
but the Mplab XC16 can't build this method.
gives the same error message for all three arrays,
expected expression before '{' token
expected expression before '{' token
expected expression before '{' token
what is the reason for that?
is there a correct method to do that in XC16?
Initialize BpfHX_iir1 in the usual way.
Use float constants and not double ones for the float array. (Append an f.)
IIRFilter BpfHX_iir1 = { //
.A = {0.131726f, 0.131726f, 0.12435f, 1.0f}, //
.a = { {-1.63410f, 0.82662f}, {-1.87089f, 0.91410f}, {-1.6652f, 0.7513f}}, //
.b = { {1, 0, -1}, {1, 0, -1}, {1, 0, -1}} //
};
All members of BpfHX_iir1 will be initialized. Those not explicitly coded above will have a zero bit-pattern.
To assign an array *1 via memcpy() at a later time is easy if the compiler is C99 compliant. Use a compound literal.
void foobar(void) {
IIRFilter BpfHX_iir1;
// v-------------------------------- compound literal ---------v
memcpy(BpfHX_iir1.A, (float[MAX_STAGES_IIR]){0.131726f, 0.131726f, 0.12435f, 1.0f}, sizeof BpfHX_iir1.A);
...
}
Or the old fashion way:
const float A0[MAX_STAGES_IIR] = {0.131726f, 0.131726f, 0.12435f, 1.0f};
memcpy(BpfHX_iir1.A, A0, sizeof BpfHX_iir1.A);
*1 Arrays cannot be simply assigned in C. They can be copied via memcpy(), just like any object.

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;

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.

Why can't I assign a struct variable using curly brackets {}?

I have the following code, why does Visual Studio underly the first bracket { in playerObj.cropImg = { 0, 0, 45, 32 }; and return an error error C2059: syntax error : '{' when I compile ?
#include <SDL.h>
#include <stdio.h>
typedef struct obj
{
SDL_Surface *pSprite;
SDL_Texture *pTexture;
SDL_Rect cropImg;
SDL_Rect pos;
} obj;
obj playerObj;
void playerObj_init(unsigned char * filename, SDL_Renderer * pRenderer)
{
playerObj.cropImg = { 0, 0, 45, 32 };
}
Your code attempts assignment.
Initialization is when you provide a value for the variable as part of a declaration.
Assignment is when you provide new values for a variable that already exists; this occurs in a statement (not a declaration).
In C90, brace-enclosed initializers can only be used in declarations. In C99 you can have literals of struct type but you have to specify the type as part of the syntax (it would be too complicated to have the compiler try to deduce it):
playerObj.cropImg = (SDL_Rect) { 0, 0, 45, 32 };
An alternative that works in C90 is to write:
SDL_Rect const newRect = { 0, 0, 45, 32 };
playerObj.cropImg = newRect;
and the compiler should optimize it.
NB. Consider using designated initializers to help with code maintainability. In either situation,
{ .w = 45, .h = 32 }

C error: expression must have a constant value

I am writing some embedded code to interface with an external device over SPI. The device has several registers of varying length and to help keep things straight I have defined the following structure
typedef struct
{
uint16_t Signed :1; // Register is signed or unsigned
uint16_t CommLengthBytes :3; // The width of the register in bytes
uint16_t Address :12; // Register address
}ts_register;
I have then defined each register in my sources as follows
static const ts_register SAGCYC = {0, 1, 0x000};
static const ts_register DISNOLOAD = {0, 1, 0x001};
static const ts_register LCYCMODE = {0, 1, 0x004};
static const ts_register IRMSA = {0, 4, 0x31A};
static const ts_register IRMSB = {0, 4, 0x31B};
static const ts_register VRMS = {0, 4, 0x31C};
etc.
I have a function that will take a pointer to an array of ts_registers and queue up the SPI transfers required to read all of the registers in the array and call a callback function to handle the reply
My issue comes when I try to make the array of ts_registers that I want to read as follows:
ts_register regs_to_read[3] = {VRMS, IRMSA, IRMSB};
This generates the error: "expression must have a constant value" 3 times (once per array element).
Since they are defined as constants, what have I overlooked?
Since they are defined as constants, what have I overlooked?
In C objects declared with the const modifier aren't true constants. A better name for const would probably be readonly - what it really means is that the compiler won't let you change it. And you need true constants to initialize objects with static storage (I suspect regs_to_read is global).
You could try assigning regs_to_read in a function called before anything else uses that array.
const doesn't make them constants at compile time. Make them #defines and the compiler
will be happy.
I think this may be a compiler issue, and it would be helpful to know your platform and how you are building this code. I just took most of your code, doctored it up to compile it, and compiled on Linux using gcc. There were no warnings.
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
typedef struct
{
uint16_t Signed :1; // Register is signed or unsigned
uint16_t CommLengthBytes :3; // The width of the register in bytes
uint16_t Address :12; // Register address
}ts_register;
int main(int argc, char **argv) {
static const ts_register SAGCYC = {0, 1, 0x000};
static const ts_register DISNOLOAD = {0, 1, 0x001};
static const ts_register LCYCMODE = {0, 1, 0x004};
static const ts_register IRMSA = {0, 4, 0x31A};
static const ts_register IRMSB = {0, 4, 0x31B};
static const ts_register VRMS = {0, 4, 0x31C};
ts_register regs_to_read[3] = {VRMS, IRMSA, IRMSB};
return(0);
}
Have you tried casting the values? It's not always the best thing to do, but will get you around the error.
Have you considered creating #define entries?
Also, please be aware consts take a bit of getting used to in C. They do not always behave the way you might expect.
If regs_to_read is declared in any function scope, the error would be cleared.

Resources