C: Behaviour of the `const` keyword - c

I've been told that if I'm coding in ANSI C to declare in the order that the variables will be used, assert that pointers are not null and that indices are within bounds, and to initialize just before usage of the variable.
If I declare a const can I initialize it after a block of assertions and code?
In Java final initializations must occur at declaration, yet is it consistent through ANSI C implementations that I can initialize a const once, but not necessarily at the time of declaration?

The Java compiler has a small amount of flow logic to allow you to initalise final variables after their declaration. This is legal Java:
final int something;
if ( today == Friday )
something = 7;
else
something = 42;
Java will detect if any branches leave the final value undefined. It won't analyse the conditions, so this is not legal Java, even though it's logically similar:
final int something;
if ( today == Friday )
something = 7;
if ( today != Friday )
something = 42;
In ANSI C89, const variables ( other than extern ) must be initialised in the statement they are declared in.
const int something = ( today == Friday ) ? 7 : 42;
The extern modifier on a declaration tells the compiler that the variable is initialised in a different complation unit ( or elsewhere in this compilation unit ).
In ANSI C99, you can mix declarations and code, so you can declare and initialise a const variable after a block of assertions and code. Portability of 1999 ANSI C remains an issue.
A work around for C89 is to note that the rules for declarations preceding code work at block scope rather than function scope, so you can do this:
#include<stdio.h>
int main ( void )
{
printf ( "wibble\n" );
{
const int x = 10;
printf ( "x = %d\n", x );
}
return 0;
}

Be aware that even in C89, you can often move the definition closer to the point of first use by introducing a bare block just for the extra scope. Before:
int a, b, c;
a = 12;
// Do some stuff with a
b = 17;
// Do some stuff with a and b
c = 23;
// Do some stuff with a, b, and c
After:
int a = 12;
// Do some stuff with a
{
int b = 17
// Do some stuff with a and b
{
int c = 23;
// Do some stuff with a, b and c
}
}
With C99 of course, you can define variables other than at the beginning of a block:
int a = 12;
// Do some stuff with a
int b = 17
// Do some stuff with a and b
int c = 23;
// Do some stuff with a, b and c

const variables are read-only and must be initialised where they're defined.
This code produces error: assignment of read-only variable 'foo' (GCC 4):
const int foo;
foo = 4;
The same goes for const pointers (note here: const int * is not a const pointer, but a pointer to const):
int * const foo;
foo = 4;

Short of the block scope and C99 declaration methods other have shown, the answer is no; you cannot defer initialization of a const variable. Anyway, const is not very useful for local variables. The main times I use the const keyword in C are:
Pointers in function arguments (or local variable pointers based on arguments) where the function is honoring a contract not to modify the pointed-to data. The const keyword helps ensure that the function implementation respects the requirement not to modify (it requires special effort casting to get rid of const) and allows this requirement to propagate through multiple function calls.
For declaring compile-time constant tables (lookup tables, predefined permanent objects, etc.) which I want stored in a read-only section of the binary so they don't use extra physical resources at runtime.
I sometimes declare local variables const if I think it will assist the reader in understanding a function, but that's pretty rare.

You can't initialize the const after declaration within the function body, but you can just open one block after your assertions:
void func()
{
int y;
// Do assertions
assert(something);
{
int const x = 5;
// Function body
}
}

If you are talking of splitting a definition
const int x = 2;
into two parts:
const int x;
x = 2;
I'm afraid that's not possible in C.
If I were you, I would try to make sure I understand the intent of the coding rules that you describe. I doubt sane coding rules would prevent initializing variables (even non-const variables).
In response to various comments:
const int * p;
is not a declaration of a const variable. It is a declaration of a non-const pointer variable to a const int.
You can declare
extern const int x;
but you can still not initialize x after having executed code, assertion checks, etc.

If you'd like to cast away const on the LHS, use this:
const int n = 0;
*((int*)&n) = 23;

Related

While swapping two values, the input of the function must be two const pointers and the return should be void

I've written the code for passing the values normally with pointers My question is how to pass these values i.e. a & b as constant pointers, if it is not already.
void swap(int *x, int *y)
{
int tmp;
tmp = *x;
*x = *y;
*y = tmp;
return;
}
int main () {
int a = 20;
int b = 12345;
printf("Before swap, value of a : %d\n", a );
printf("Before swap, value of b : %d\n", b );
swap(&a, &b);
printf("After swap, value of a : %d\n", a );
printf("After swap, value of b : %d\n", b );
return 0;
}
const in C generally goes after the type, and the * is part of the type, so the type declaration of an integer pointer constant is:
int * const
You may have tried int const *, and found that to not work. That's because, to repeat, generally const applies to the thing on its left.
Opinion: This is why I hate the pattern of writing const first, like const int. It only works because the language has a special case - if there is nothing to the left of the const, it applies to the thing on its right - and since most people learn by example, every occurrence of const at the beginning of a type declaration contributes to mis-teaching people trying to learn the language.
Tip: I like reading and saying const as "which is constant", because that phrase clearly refers to the thing before it, so it matches the left-to-right order of the parts of a type declaration: int const then reads as "an integer which is constant" and int * const reads as "an integer's address which is constant".
Putting that together with your swap function we get
void swap(int * const x, int * const y)
Opinion: This is also why I dislike * in a declaration "touching" the name. I do int * foo instead of int *foo because it's more consistent with other type declarations like int * const foo, which I feel is more important than consistency with the unary operator placement in dereferences like *foo.
But you should know that in C, or at least in all real and most conceivable implementations of C, it doesn't actually change code behavior to make function parameters const like that - the parameter itself is private to the function, so the function can't change it. The only way it could realistically make a difference for the actual code is if you had a C compiler which could better optimize a function if you tell it that it won't be modifying its own parameters, but most optimizing compilers can just notice if a parameter isn't being modified within a function. Of course, it can still be useful as a way of telling people reading your code what your intent with the parameters is, and if you have a habit of declaring things const any time you don't have specific intent to change them, you're more likely to have computers catch certain mistakes (like if you have a parameter named similarly to a variable in your function, and you mean to modify one but accidentally type the other - if the other was const, simple tooling can catch the mistake).
Arguments are passed by value, and values are not const or non-const; only objects can be qualified that way. You can qualify the function parameters (which are objects that are initialized to the argument values), and that just means the function will not change the values of the parameters:
void swap(int * const x, int * const y)
{
// x and y are not changed, although the objects they point to are changed.
int temporary = *x;
*x = *y;
*y = temporary;
}
If you want to make the parameter types pointers to const objects, that is also possible. As long as a pointer points to an object that was not defined with const, the behavior of removing the const through a conversion and using it to modify the object is defined:
void swap(const int *x, const int *y)
{
/* ncx and ncy are set to the original pointers to non-const
that became the pointers to const that are x and y.
*/
int *ncx = (int *) x, *ncy = (int *) y;
int temporary = *ncx;
*ncx = *ncy;
*ncy = temporary;
}

Is it a good practice to group related constants using structs in C?

I was wondering if it would be a good idea to use structs as pseudo namespaces (à la C++) to group constants which are functionally or conceptually related to each other.
static const struct {
const unsigned int START;
const unsigned int END;
} COUNTER = {.START = 1, .END = 100};
Is there any downside to this? If not, is it redundant (or maybe even unconvenient) to have both the struct instance and its members declared as const? Where should the constantness of these values be stated?
I was wondering if it would be a good idea to use structs as pseudo namespaces
Well, it CAN be a good idea. It's not intrinsically bad. An argument against is that if you feel that you need namespaces, then it's likely that C is the wrong language in the first place. But it can be used this way, and it is sometimes used this way.
Where should the constantness of these values be stated?
It's in general enough to declare the whole struct as const. But beware with pointers. This code is valid and will print "42":
int x = 5;
const struct {
int *p;
} S = {.p = &x };
int main()
{
*(S.p) = 42;
printf("%d\n", x);
}
In the above code, you are not allowed to change S.p so that it points to something else, but there is a difference between a const pointer and a pointer to const. So for pointer, it could be a good idea to add an extra const.
To clarify, the pointer p will be declared like it was a int * const p which means you cannot change the pointer itself, but in order to protect the data it's pointing to, you need const int *p. To get both, use const int * const p, but if the struct is declared as const, you'll get one of them "for free" so const int *p is enough to get both.
And if you consider pointers to pointers, well, think it through for a long time and test it to make sure it works the way you want.
From comments:
Why not enums?
Because this is not valid:
enum S {a = 5};
enum Y {a = 6};
The compiler will tell you that a is already defined. So enums is not good for emulating namespaces. Also, you cannot use enums for non-integers.
Is it a good practice to group related constants using structs in C?
It's opinion based. If it works for you, do it.
I wouldn't do like that i C. Instead I use #define
Like:
#define GROUPNAME_NAME
so in your case I would do
#define COUNTER_START 1
#define COUNTER_END 100
In C++ I would do:
const unsigned int COUNTER_START = 1;
const unsigned int COUNTER_END = 100;
The difference between C and C++ is due to differences in language specification.

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.

How can I add 2 ints in a const definition in 1990?

Welcome to the 1990s,
I am using an old Mac os 7.01 API, and I need to define a "Rect" struct with an array of four constants. Sadly, I always get the "requires constant" error on that "Rect" definition. We are talking about a 24 year old compiler, though.
Rect shapeRect = {100, 100, 200, 200}; // Works
const int shapeSize = 10;
int shapeX = 0; // Cannot be const
int shapeY = 0; // Cannot be const
Rect shapeRect = {shapeX - shapeSize, shapeY - shapeSize, shapeX + shapeSize, shapeY + shapeSize }; // Error: "requires constant"
I've tried defining multiple const with all the 4 values calculated, but I still get the same error on the same line.
const shapeRectT = shapeX - shapeSize;
...
Rect shapeRect - {shapeRectT, ...};
My guess is that the shapeRectT const is not a constant? I am a beginner in C, but I believe this problem is probably easy to repair, but this is an old compiler, and things may be different, and I don't know if newer C standards changed things about this stuff.
EDIT: I found the documentation for this API (QuickDraw): https://developer.apple.com/legacy/library/documentation/mac/pdf/ImagingWithQuickDraw.pdf
The problem is related to limitations of C89 that we all now have forgotten.
At that time you could not have non-litterals in the initializer of a global struct variable. Non-litteral expressions were only allowed for local struct variables.
This restriction was due to the fact that the code execution really started in those time with main() (in fact a stub initializing stdin,stdout and the environment and then calling main). There was no code generated for global initialisation. Only values that where loaded as part of the image from the executable.
I just could confirm this behaviour with my old microsoft compiler. It was MSDOS, but from February 1990, so pretty close to the one you use:
struct R {int a, b; }; /* simple structure for the demo */
struct R a = { 1,2 }; /* global variable with litteral init: ok ! */
const int v1 =10;
const int v2 =20;
struct R z = { v1,v2 }; /* Error message, "illegal initialization" */
int main()
{
struct R w = { v1,v2}; /* here it is accepted, because corresponding
initialisation code could be generated/executed
as part of the function */
return 0;
}
Yes, there is a difference in aggregate (and union) initialization between C89 and C99. A quote from the C99 rationale (PDF page 95):
The C89 Committee considered proposals for permitting automatic aggregate initializers to consist of a brace-enclosed series of arbitrary execution-time expressions, instead of just those usable for a translation-time static initializer. Rather than determine a set of rules which would avoid pathological cases and yet not seem too arbitrary, the C89 Committee elected to permit only static initializers. This was reconsidered and execution-time expressions are valid in C99.
Some C89 compilers implement this as extension. Yours doesn't. You can fix the error like this:
Rect shapeRect;
shapeRect.top = shapeX - shapeSize;
shapeRect.left = shapeY - shapeSize;
shapeRect.bottom = shapeX + shapeSize;
shapeRect.right = shapeY + shapeSize;
Do it manually. (Not recommended.)
Make some constants you use for initializing (not const-qualified variables).
enum {shapeX_Init = 0, shapeY_Init = 0, shapeSize_Init = 10};
const int shapeSize = shapeSize_Init;
int shapeX = shapeX_Init; // Cannot be const
int shapeY = shapeY_Init; // Cannot be const
Rect shapeRect = {shapeX_Init - shapeSize_Init, shapeY_Init - shapeSize_Init,
shapeX_Init + shapeSize_Init, shapeY_Init + shapeSize_Init };

function pointer with variable inputs

In C, I am trying to pass a single-variable function into an optimization routine (optimization_routine). The optimization routine takes as input a pointer func1ptr to a function of a single float variable. However, I need to be able to pass multiple variables into this function. Thus, I am trying to construct a function pointer of one variable where all but the first inputs are "constants" into the function variable (sort of analogous to a partial derivative in calculus). I think I can do this with function pointers, but I can't figure out a syntax that makes sense.
That is, I have a function like this:
float function_all_inputs( float A, int B, float C, char D);
The optimization function requires a pointer like this:
typedef (*func1ptr)(float);
void optimization_function( func1ptr fp );
Thus, I want to construct a function of this form:
// create a function of A only at runtime using inputs B,C,D
func1ptr fp = ( & function_all_inputs(A,B,C,D))(A);
The function pointed to by fp should have the signature:
float function_one_input(float A);
Inputs B, C, and D are calculated elsewhere in the code, and thus are not known at compile-time; however, they are constant inside optimization_function.
I think I can do this in pure C using function pointers, however, I can't figure out the correct syntax. None of the examples I found online cover this case. Any advice you can provide would be appreciated.
It sounds like you are asking how to create a closure to capture parameters in C, and you can take a look at some options in the linked question.
However, without custom extensions, I think you will need to use global variables to achieve the effect you are looking for.
// Pass this wrapper with the name "wrapper" into the function
// that requires a function pointer
void wrapper(float a) {
// Where last four arguments are global variables that are computed first.
function_all_inputs(a, b, c, d, e);
}
// No need to create an explicit function pointer.
// Passing the name of the function is sufficient.
optimization_function(wrapper);
You need to write a wrapper function, like
int b;
float c;
char d;
int wrap(float a) {
return function_all_inputs(a, b, c, d);
}
Consider concurrency an re-entrancy though:
If multiple threads can use the wrapper, and need it to pass different data, make those globals thread-local:
_Thread_local int b;
If you need full re-entrancy, things get complicated:
You need to (also) save the variables before using a nested invocation with different parameters.
Writing a second (and maybe third) version of the wrapper using different globals may be better.
If you need more active at the same time, you can try a pool of those functions, though it gets unwieldy really fast. Better change your optimization-function by adding a context-parameter, and pass those extra-parameters with that.
For full freedom, you really need a way to write functions at runtime, at least enough to recover a context-pointer. That's not possible in pure C though.
If sizeof(float) >= sizeof(void*) on your platform, then you can "hack" it as follows:
typedef struct
{
float a;
int b;
float c;
char d;
}
params;
int function_all_inputs(float a, int b, float c, char d)
{
...
}
int function_one_input(float f)
{
params* p;
memcpy((void*)&p, (void*)&f, sizeof(void*));
return function_all_inputs(p->a, p->b, p->c, p->d);
}
int optimize()
{
float f;
params v;
params* p = &v;
v.a = ...;
v.b = ...;
v.c = ...;
v.d = ...;
memcpy((void*)&f, (void*)&p, sizeof(void*));
return optimization_function(function_one_input, f);
}
You weren't very consistent in your question about the return-value type, so I used int.
This may be overkill, but libffi supports creating closures in the following way:
#include <stdio.h>
#include <ffi.h>
typedef struct BCD { int B; float C; char D; } BCD;
void function_one_input_binding
(ffi_cif* cif, int* result, void** args, BCD* bcd) {
*result = function_all_inputs(*(float*)args[0], bcd->B, bcd->C, bcd->D);
}
int main() {
ffi_cif cif;
ffi_type* args[1];
ffi_closure* closure;
int (*function_one_input)(float);
// Allocate a closure.
closure = ffi_closure_alloc(sizeof(ffi_closure), &function_one_input);
// Tell libffi the parameter and return types.
args[0] = &ffi_type_float;
ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_int, args);
// Bind closure data.
BCD bcd = { .B = 1, .C = 2.5, .D = 'x' };
ffi_prep_closure_loc(
closure, &cif, function_one_input_binding, &bcd, function_one_input);
// Call the function.
int result = function_one_input(42.5);
// Free the allocated closure.
ffi_closure_free(closure);
return 0;
}

Resources