Intended constant variables that need to be initialized at runtime - c

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.

Related

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.

Initialising a static const variable from a function in 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;

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.

C - how to protect a a variable from being accidentally changed after a certain point in the function

C - how to protect a variable from being accidentally changed after a certain point:
For example, in a C program, I declared an integer and changed it's value several times in the first part of the program. But then after a certain point I want to keep its value from being accidentally changed, or at least get a warning when any attempt to change its value happens. How do I do that?
You can't.
A possible solution would be to move the part of the function that modifies the variable into a separate function. That function would return the value of the variable which can be used to initialize a const variable:
int determine_value_of_a()
{
int result = 0;
/* Modifications of result. */
return result;
}
void f()
{
const int a = determine_value_of_a();
}
If using preprocessor macros is acceptable, then you can do this:
{ // Function body starts here.
int x = …;
… // Change x as desired here.
const int y = x;
#define x y;
… // “x” is actually the const y here.
#undef x
}
Generally, though, I would not recommend it. If you cannot trust the body of a single function to do things correctly, then the function is too complicated and ought to be restructured, as by calling another function to provide the value of the object.
Put the variable in a opaque struct with an indication of whether it can be changed.
Access the variable, both for getting and changing the value, from a function.
If the indication for changeability if off, the function does not allow changes
#include "swinger.h"
int main(void) {
struct moodswinger *var;
var = newswinger();
setvar(var, 42);
getvar(var);
swing(var, 0);
setvar(var, -1); /* oops */
}
The file swinger.h declares the functions.
The file swinger.c defines the struct and code.
int x;
x = …; // This is okay.
{
const int y = x; // Make a copy of x.
{
const int x = y; // Make a const copy of x that hides the original.
/* The compiler should produce a diagnostic if you
attempt to modify x here.
*/
}
}
Or, if you do not want the indenting to change:
int x;
x = …;
{ const int y = x; { const int x = y;
…; // x is const here.
} }
The only way you could do that would be
(a) to use a function to initialize the variable..
int main( int argc, char** argv )
{
const int myVar = initMyVar();
...
}
or (b) pass the variable into another function that does the other work...
void myWorkerFunc( const int myVar )
{
...
}
int main( int argc, char** argv )
{
int myVar = initMyVar();
...
myWorkerFunc( myVar );
}
Set a conditional breakpoint on it in your debugger. Then you will know if it ever changes. You could also write a "watchdog" type thread that scans your var every so often and warns on change, but that won't be immediate.
Neither of these are within the realm of C directly, but would help you determine if your var was erroneously changed.

how to initialize a global const pointer?

I have a variable which is the head to a linked list. I want to make it const because it should never be changed, the variable is used throughout the program, so I thought I should make it a global const. The problem is that I couldn't initialize it after I declared it const.
How can I get around this problem?
typedef struct PT {
int x;
int y;
struct PT *next;
} POINT;
//globals
POINT * const mypoint_head;
int main(int argc, char *argv[])
{
int size = 100;
mypoint_head= InitPoint(size); // error C2166: l-value specifies const object
//rest of code
}
POINT* InitPoint(int size)
{
POINT *tmp;
POINT *orig;
int a = 10;
int b = 1000;
orig = (POINT*) malloc (sizeof(POINT) * size);
if(orig == NULL)
return NULL;
tmp = orig;
for (i = 0; i < size; i++)
{
tmp->x = a++;
tmp->y = b++;
if (i == size -1) {
tmp->next = NULL:
}
else {
tmp->next = tmp+1;
}
tmp++;
}
return orig;
}
You can't - that's the whole point of const.
You are correct in that the variable declared const can never be changed. Unfortunately, your mypoint_head= InitPoint(size); line counts as trying to change the variable. You have to initialize the const variable with a value when it is declared.
Try something like this instead:
//globals
static POINT head_of_list;
POINT* const mypoint_head = &head_of_list;
Now, you can initialize the list using:
mypoint_head->next= InitPoint(size-1);
The head-of-list object was declared statically, so it always exists and you eill need to adjust your InitPoint parameters appropriately. You can also have an extern reference to the pointer in another file without having to make the object it points to directly accessible (for what it's worth).
Nobody has suggested this yet:
int main(int argc, char *argv[])
{
int size = 100;
// cast address of mypoint_head to a non-const pointer:
POINT ** nc_pmh = (POINT **)&mypoint_head;
// use the address to set mypoint_head:
(*nc_pmh) = InitPoint(size);
//rest of code
}
This may not work in C++, where it may not really supply space for const objects.
BTW: This is not generally good practice. In this case, however, it works out well.
BTW: you'll want to check the return from InitPoint(), and act accordingly (call exit(), probably).
don't have a global const pointer as your interface to everything else.
use a function :-
static POINT * mypoint_head;
POINT* point_head()
{
return mypoint_head;
}
Remove the const qualifier from the global declaration and declare rest_of_code as a function that takes the const-qualified version of the pointer.
//globals
POINT * mypoint_head;
void rest_of_code(POINT* const mypoint_head)
{
mypoint_head = NULL; // this errors out now
}
int main(int argc, char *argv[])
{
int size = 100;
mypoint_head= InitPoint(size); // no longer errors out
//rest of code
rest_of_code(mypoint_head);
}
You have to use an initializer in the declaration:
static POINT mypoint_data[100];
POINT * const mypoint_head = &mypoint_head;
Then change your InitPoint function to take a pointer to the dataspace instead of calling malloc and pass it mypoint_data
You can also stick extern POINT * const mypoint_head; in a header file so its accessable in other compilation units.
(assumes c) const have to be initialized when they are declared and they cannot be evaluated . Maybe you could use a const pointer and make it point to your head and expose it to the rest of the code.
If i have to achieve may be i will expose the variable by a getListHead() function and give it some obscure name :)
Wonders what the use case is though. I would make my list work even if its head pointer changes. (if i have a const head, if i have to delete the head node i will have to shift the elements like in an array)
I can't believe that no one has yet suggested const_cast.. It works just as fine for constant pointers.
const_cast<POINTER *>(mypoint_head) = InitPoint(size);
Simple as that, no extra variable declaration, nothing.

Resources