Initialising a static const variable from a function in c - c

I have recently run into some trouble while trying to perform the following logic:
static const int size = getSize();
int getSize() {
return 50;
}
The error I have received is initialiser element is not constant
Having read online I understand that this issue is because the compiler evaluates the static const expression at compilation and therefore cannot know what the value is supposed to be.
My question is how do I get around this?
If I have a library that contains many functions but they all require this logic how are they supposed to use it without having to calculate it each time?
And even if they have to, what if the logic itself can change throughout runtime but I only ever want the first value I receive from the function?
Perhaps I should clarify that the logic in getSize is just an example, it could also contain logic that retrieves the file size from a specific file.

Unlike in C++ you cannot initialize global variables with the result of a function in C, but only with real constants known at compile time.
You need to write:
static const int size = 50;
If the constant must be computed by a function you can do this:
Dont declare static const int size = ... anymore, but write this:
int getSize()
{
static int initialized;
static int size;
if (!initialized)
{
size = SomeComplexFunctionOfYours();
initialized = 1;
}
return size;
}
int main(void)
{
...
int somevar = getSize();
...
That way SomeComplexFunctionOfYours() will be called only once upon the first invocation of getSize(). There is a small price to be paid: each time you invoke getSize(), a test needs to be performed.
Or you can initialize it explicitely like this, but then size cannot be const anymore:
static int size;
void InitializeConstants()
{
size = SomeComplexFunctionOfYours();
}
int main(void)
{
InitializeConstants();
...
int somevar = size;
...

The compiler needs to know the value of your constant variable at the compilation time, because its a constant.
Also you can't initialize a variable with a function.
You should do something like this :
#define SIZE 50
static const int size = SIZE;

Related

C89: declare large const array, then use it, then initialize it

This is purely for readability. I want to have a very large constant array of values, but it makes my file a lot less pleasant to read. So I'd like to have that array initialized after use, though I want it to be constant. I know this is probably impossible, but it's probably also very common. So what workarounds are there ? I do not want to create a separate file right now.
Some thing like :
static const float array_of_values[1000];
float getValueFromArray(int index)
{
return array_of_values[index];
}
array_of_values = {0.123f, 0.456f, 0.789f ...};
First of all what you're doing is not initialization, it's plain assignment. And you can't assign to an array. And you can't have general statements outside of functions. If you want to initialize the array, you need to do it when defining the array.
With that said, you have to remember (or learn) that any definition without explicit initialization is tentative.
That means you can create a tentative definition, basically to get the declaration out of the way. Then at a later place in the source file you can add the actual definition:
static const float array_of_values[1000];
float getValueFromArray(int index)
{
return array_of_values[index];
}
static const float array_of_values[] = { 0.123f, 0.456f, 0.789f, /* ... */ };
These are common solutions to make the file less cumbersome to read:
static const float array_of_values[1000] = { MACRO }; // macro being an initalizer list
or
static const float array_of_values[1000] =
{
#include "initlist.h"
};
I would personally recommend the macro version since it's more flexible and less mysterious. You could still declare the macro in a separate header file.
There's also tentative definitions which is generally a bad idea, again because it makes the code mysterious and hard to read:
static const float array_of_values[1000];
float getValueFromArray(int index)
{
return array_of_values[index];
}
static const float array_of_values[1000] = {0.123f, 0.456f, 0.789f};
#include <stdio.h>
int main (void)
{
printf("%f\n", array_of_values[0]);
printf("%f\n", getValueFromArray(0));
}
Try this:
#include <stdio.h>
static float array_of_values_base[1000]; // the effective array has "base" in its identifier
static const float *array_of_values = array_of_values_base; // your array is now a pointer
float getValueFromArray(int index)
{
return array_of_values[index];
}
int main(void) {
array_of_values_base[0] = 0.123f;
array_of_values_base[1] = 0.456f;
array_of_values_base[2] = 0.789f;
// ...
printf("value at index 1 is %f\n", getValueFromArray(1));
}

Setting one variable equal to another in C

I am writing a code in C. It is in an environment with precoded functions, so I can't explain it completely. I wanted to iterate over a variable but this wasn't working. I eventually figured out this was because the variable was not defined globally but in a function, and was being redefined every time the function was called.
Now, at the top of my code, globally, I want to write the following code.
int killing_time = 20000;
int killing_period;
killing_period = killing_time;
The compiler gives me the following errors:
data definition has no type or storage class
Don't I clearly define it to be an integer?
initializer element is not constant
If I define killing_time as const int killing_time = 20000 it still gives the same error:
type defaults to ‘int’ in declaration of ‘killing_period'
I could of course define killing_period to be 20000 and just start iterating over that, but I want to know what is going on.
I hope we can figure this out together.
killing_period = killing_time; is not a valid statement in the global scope.
You can use assignment on declaration, but assigned variable (initializer element) must be constant:
const int killing_time = 20000;
int killing_period = killing_time;
Anyway, you shouldn't do it like that.
There's more than one way to do this, one of them is to pass the address of your iterator to the function where you use it, that way the changes made in the scope of the function are permanent:
void f1(int* i){
(*i)++; //will increment i
}
void f2(int* i){
(*i)++; //will increment i
}
int main ()
{
int i = 0;
f1(&i); //pass the address of i
f2(&i); //pass the address of i
printf("%d", i); // i = 2
return 0;
}
killing_period = killing_time; is executable code and you simply can't have executable code outside functions.
Nor can you do this:
int killing_time = 20000;
int killing_period = killing_time; // wrong
Because these are file scope variables and therefore have static storage duration. And variables with static storage duration can only be initialized by what C calls a constant expression. 20000 above is an integer constant expression, but killing_time isn't.
The simple fix is to do something like this instead:
#define KILLING_TIME 20000
...
int killing_time = KILLING_TIME;
int killing_period = KILLING_TIME;
killing_period = killing_time; is your problem. It is an executable statement and not allowed in global space... it must be within a function.
Still not sure what you are after, but would the following help?
int killing_time = 20000;
int killing_period = -1; // negative if not yet set
int your_function(void)
{
if ( killing_period < 0 ) {
/* one-time initialization on the first call */
killing_period = killing_time;
}
return killing_period;
}
If you need multiple functions setting killing_period it may be be best to burry that in a separate function dedicated to the test and set, or perhaps a macro.

Const int to int doesnt work properly

If I convert const int to int inside a void it works.
But when I create an extern const int it doesn't.
void ReadFromEpprom()
{
int Start = 343;
const int End=Start; //This works
}
Example 2
Header File
extern const int End;
Source file
const int End;
void ReadFromEpprom()
{
int Start = 343;
End=Start; //This doesn't work
}
In second situation I get error:
(364) attempt to modify object qualified const
How can I solve this?
Should I make it with another way?
When you declare a constant variable this means the variable will not change.So it makes sense that constant variables must be initialized immediately.You are doing this in your first example which is correct.In your second example you have a constant variable and then you are trying to modify it's value.This is incorrect since the variable is already constant.
The extern here is a red herring.
If you use const int End then you need to initialise End at the point of this declaration. That's because it's const.
So const int End = Start; works fine, but const int End; is not syntactically viable.
In C you can't arrange things so you have a const at global scope and a function that sets the value at run-time. But what you could do is embed the value in a function (as as static), and call that function to initialise and subsequently retrieve the value.
Initialiazation versus assignment:
A const object can be initialized (given a value at the declaration), but not assigned (given a value later).
This is initialization, and "works". It is initialization the local variable End that exist inside ReadFromEpprom().
void ReadFromEpprom()
{
...
const int End=Start; //This works
End=Start; attempts to assigned End that exist at file scope, outside of ReadFromEpprom(). const objects cannot be assigned.
const int End;
void ReadFromEpprom()
{
...
End=Start; //This doesn't work
}
How can I solve this?
Let external code to read localEnd via a function ReadEnd(), yet allow local code to write localEnd.
static int localEnd;
int ReadEnd() {
return localEnd;
}
void ReadFromEpprom() {
int Start = 343;
localEnd = Start;
}
I agree with all the other answers.
It seems that you want to initialize a const value with a value that will be determined at run time, which is impossible.
What you can do is two workarounds.
Remove const. Add a comment near its definition that the variable is set only once in the very beginning.
Use a function instead of a const int variable; implement the "run code only once" idea inside this function.
Header file:
int CalcEnd();
Source file:
int CalcEnd()
{
static int init_done = 0;
static int result;
if (!init_done)
{
result = 343; // or any complex calculation you need to do
init_done = 1;
}
return result;
}
Note how the function uses static variables and logic to do initialization only once.
If you use the function idea, and don't want to remember typing the parentheses in the function call (CalcEnd()), you can define a macro:
#define End MyCalcEnd()
This will make it appear as if End were const int variable, when actually it's a function call. This usage of macros is controversial, use it only if you are sure it will not lead to confusion later.

When do programmers use 'static' and 'const' keywords?

I am doing research on static and const keywords.
Static: Use the static modifier to declare a static member, which belongs to the type itself rather than to a specific object.
const: You use the const keyword to declare a constant field or a constant local. This keyword specifies that the value of the field or the local variable is constant, which means that it can't be modified.
I would like to know about example when programmers would use static and const keywords.
const variables, or constant, would be used to declare a value that won't change or you want to prevent from being changed. For example, Pi could be declared as a constant in C++.
const double kPi = 3.14159265359;
static variables are a bit different. There is only one instance of the static variable that persists across classes\functions.
For example:
void foo()
{
static int bar = 0;
printf("%d\n", bar);
++bar;
}
int main()
{
int i;
for(i = 0; i < 5; ++i)
{
foo();
}
}
Would print:
0
1
2
3
4
Even though bar goes out of scope, its value is still in memory, so its only initialized once. Each time the foo() is called, that value gets incremented.
Edit:
To clarify, the compiler will actually reserve memory for the static variable within the assembly code that it produces. Additionally, the static keyword also tells the compiler to initialize the variable exactly once. The scope of the variable is the same (inside the foo function), but it is only initialized once in the above case. Automatic variables (such as int i) are pushed onto the call stack when the function is called.
(All of this is for Langage C++)
Hi, you can use const and static keywords in few cases, for exemple :
Const
First, used to say that the variable cannot be modified.
int main()
{
const int toto[4] = {0, 1, 2, 3};
return (0);
}
// We cannot modify toto after it declaration, why is it usefull? It keeps the state of your program design
Second, used to say that a method do not modify the object state.
class toto
{
int i;
public:
int geti() const;
}
// All getter in CPP use it. Why is it usefull? Developper who use the class know that he do not modify the object state
Third, used to say that the parameter pass to a function isn't modify by the function.
int function(const std::string &str)
{
// function cannot modify the object string pass in parameter
}
Static
First, used to say that a implemented function is know only inner a single file.
static int fct()
{
return (0);
}
// You can ony call function fct() if you are inner the file who it is implemented
Second, used to say that a argument or method is common to all object of the same class.
class toto
{
public :
static int getLol();
};
// Every object totoObj1, totoObj2 ... will call same function
Third and the last one, used to say that a variable do not change state between multiple call of the same function where it is declared
void fct()
{
static i = 0;
std::cout << ++i << std::endl;
}
// This function are going to print 1 then 2 then 3 ...
If you have any questions, you are welcome :)
If you want to have any variable/method to be available irrespective of an object you go for a static member but if you want the same to be unmodifiable as well then const is the solution. Following example can help you understand this.
In below example
PI is defined as a constant and can not/should not be changed
ONLINE holds number of users online, it can change but should be available irrespective of objects
public class Example
{
//PI should not be changed, with reasons known that it is a constant
public const double PI = 3.14;
//Users currently using the application
public static int ONLINE = 0;
public Example(){ ONLINE++; }
public void dispose(){ ONLINE--; }
public static int loggedInUsers(){ return ONLINE; }
public void GetArea(int radius){return PI*radius*radius; }
}

Intended constant variables that need to be initialized at runtime

I have a variable that I want to initialize at runtime before the rest of the program runs. After initialization, I don't want the value of the variable to change. Is there any C language construct to go about doing this ?
Let my main C program is contained in a file Prog.c
//Contents of Prog.c
//...includes.. and variable initialization
int main(..)
{
//Initialize variables here
//.. Huge program after this where I don't want these constants to change
}
You can do it indirectly through const pointers, at least:
typedef struct {
int answer;
} state;
const state * state_init(void)
{
static state st;
st.answer = 42; /* Pretend this has to be done at run-time. */
return &st;
}
int main(void)
{
const state *st = state_init();
printf("the answer is %d, and it's constant\n"," st->answer);
}
This way, all main() has is a const pointer to some state which it cannot modify.
A constant global should work, yes?
const int val = 3; // Set before main starts
// const, so it will never change.
int main(void)
{
printf("%d\n", val); // using val in code
}
However, if the value isn't known at compile-time, you can set it at run-time this way:
const int const* g_pVal;
int main(void)
{
static const int val = initialize_value();
g_pVal = &val;
printf("%d\n", *g_pVal);
}
The only way I can think of is if you read your value as a non constant and then call a function which take a constant value and pass your variable to it. Inside the function you make all the wished operations.

Resources