C const/non-const versions of same function - c

Suppose in C I have the functions
type* func (type*);
const type* func_const (const type*);
such that they both have the exact same internal logic.
Is there a way I can merge the two into one function, where if given a const type, it returns a const type; and if given a non-const type, it returns a non-const type? If not, what is a good way of dealing with this? Define one in terms of the other via explicit casting perhaps?

You can't automate it, but you can certainly have the logic in a single location:
const type* func_const (const type*)
{
/* actual implementation goes here */
}
type* func (type* param)
{
/* just call the const function where the "meat" is */
return (type*)func_const(param);
}

Do like the standard C library functions do and just take a const-qualified argument while returning a non-const-qualified result. (See strchr, strstr, etc.) It's the most practical.

Related

Why can't const functions in Rust make calls to associated functions?

This:
const fn pow2(exp: u32) -> u32 {
u32::pow(exp, 2)
}
Results in a compiler error:
error[E0015]: calls in constant functions are limited to constant functions, struct and enum constructors
Is there a way to do this?
I'd like to do:
pub const MY_BITMASK: u32 = pow2(4);
A const function cannot call a non-const function. This is because const functions need to be able to run during compilation, so they can't call a non-const function which can only be evaluated at runtime. Since u32::pow is not a const function, you can't call it from a const function.
The question now becomes: Why isn't u32::pow a const function? And the reason for that is a current limitation of const functions: They can only contain a subset of the language. Notably, they can't contain loops or assignments. Since u32::pow uses both of these, it can't be marked as const and therefore can't be called from const functions.
Note that there isn't any limitation of calling associated functions from const functions, as long as the associated function is marked const. And u32::pow is not an associated function in any case: you can call it as e.g. x.pow(y).
Update: Const functions gained a lot more language features they can use in Rust 1.46 (including if, while, &&, etc.), and the integer types' pow functions were made const in Rust 1.50.

Choosing const vs. non-const pointer for user data

Consider a simple, re-usable library. It has a object for the current state,
and a callback function to feed it input.
typedef struct Context_S Context_T;
typedef size_t (*GetBytes_T) (Context_T * ctx, uint8_t * bytes, size_t max);
struct Context_S {
GetBytes_T byteFunc;
void * extra;
// more elements
};
void Init(Context_T * ctx, GetBytes_T func);
int GetNext(Context_T * ctx); // Calls callback when needs more bytes
User might need some extra data for callback (like file pointer). Library
provides functions to have 1 extra pointer:
void SetExtra(Context_T * ctx, void * ext); // May be called after init
void * GetExtra(Context_T const * ctx); // May be called in callback
However, if user extra data is constant, it would require him to cast constness
away before setting the data. I could change the functions to take/return const,
but this would require extra cast in callback, if data should not be constant.
void SetExtra(Context_T * ctx, void const * ext);
void const * GetExtra(Context_T const * ctx);
Third alternative would be to hide cast inside the function calls:
void SetExtra(Context_T * ctx, void const * ext);
void * GetExtra(Context_T const * ctx);
Is it good idea to hide cast in this case?
I'm trying to find balance with usability and type safety. But since we are
using void* pointers, lot of safety is gone already.
Or am I overlooking something worthy of consideration?
The C standard library has similar problems. Notoriously, the strchr function accepts a const char * parameter and returns a char * value that points into the given string.
This is a deficiency in the C language: Its provisions for const do not support all the ways in which const might be reasonably used.
It is not unreasonable to follow the example of the C standard: Accept a pointer to const and, when giving it back to the calling software, provide a pointer to non-const, as in your third example.
Another alternative is to define two sets of routines, SetExtra and GetExtra that use non-const, and SetExtraConst and GetExtraConst that use const. These could be enforced at run-time with an extra bit that records whether the set context was const or non-const. However, even without enforcement, they could be helpful because they could make errors more visible in the calling code: Somebody reading the code could see that SetExtraConst is used to set the data and GetExtra (non-const) is used to get the data. (This might not help if the calling code is somewhat convoluted and uses const data in some cases and non-const data in others, but it is better to catch more errors than fewer.)
For a standard "hack away" functional program design, it is quite simple:
If the function modifies the contents of a pointer parameter, the pointer should not be const.
If the function does not modify the contents of a pointer parameter, the pointer should always be const.
But in your case, it would rather seem that you are doing a proper object-oriented design, where your code module is the only one who knows what Context_T is and what it contains. (I take it the typedef on the first row is actually in the h file?)
If so, you cannot and should not make the pointer const. Especially not if you are implementing true OO encapsulation using incomplete type ("opaque" type), because in that case the caller can't modify the contents anyhow: the "const correctness" becomes superfluous.

What is meaning of a pointer to a constant function?

Pointers can be declared as pointing to mutable (non-const) data or pointer to constant data.
Pointers can be defined to point to a function.
My coworkers and I were discussing the use of "const" with pointers and the question came up regarding the use of const with function pointers.
Here are some questions:
What is the meaning of a pointer to a constant function versus a
pointer to a non-constant function?
Can a function be const?
Can a function be non-const (mutable)?
What is the proper (safe) syntax for passing a function pointer?
Edit 1: Function pointer syntax
typedef void (*Function_Pointer)(void); // Pointer to void function returning void.
void function_a(Function_Pointer p_func); // Example 1.
void function_b(const Function_Pointer p_func); // Example 2.
void function_c(Function_Pointer const p_func); // Example 3.
void function_d(const Function_Pointer const p_func); // Example 4.
The above declarations are examples of treating a function pointer like a pointer to an intrinsic type.
A data, variable or memory pointer allows for the above combinations.
So the questions are: can a function pointer have the same combinations and what is meant by a pointer to a const function (such as Example 2)?
In C, there's no such thing as a function being const or otherwise, so a pointer to a const function is meaningless (shouldn't compile, though I haven't checked with any particular compiler).
Note that although it's different, you can have a const pointer to a function, a pointer to function returning const, etc. Essentially everything but the function itself can be const. Consider a few examples:
// normal pointer to function
int (*func)(int);
// pointer to const function -- not allowed
int (const *func)(int);
// const pointer to function. Allowed, must be initialized.
int (*const func)(int) = some_func;
// Bonus: pointer to function returning pointer to const
void const *(*func)(int);
// triple bonus: const pointer to function returning pointer to const.
void const *(*const func)(int) = func.
As far as passing a pointer to a function as a parameter goes, it's pretty simple. You normally want to just pass a pointer to the correct type. However, a pointer to any type of function can be converted to a pointer to some other type of function, then back to its original type, and retain the original value.
According to the C spec (C99, section 6.7.3):
The properties associated with qualified types are meaningful only for
expressions that are lvalues.
When the spec says "qualified types", it means things defined with the const, restrict, orvolatile keyword. Snice functions are not lvalues, the const keyword on a function isn't meaningful. You may be looking at some sort of compiler-specific extension. Some compilers will throw an error if you try to declare a function as const.
Are you sure that you're looking at a pointer to a constant function and not a constant pointer to a function (that is, it's the pointer that's const, not the function)?
Regarding #4: see this guide for a helpful overview of creating, passing, and using function pointers.
Under C, there is no such thing as a const function. const is a type-qualifier, and so can only be used to qualify a type, not a function. Maybe you mean a const pointer to a function or a non-const pointer to a function?
In C++, methods can be const. If a method is const, it means that after you call that method, the object containing the method will be in the same state as before you called the method (none of the instance variables[1] have been modified). Thus, you can point to a const method and a non-const method, and those methods are different.
You can accept a function pointer in an argument list as retType (*variableName)(arguments).
[1] Unless they are mutable.
In C, functions can be const if you are in the world of GCC! Functions can be declared const through the use of attributes attached to declarations of functions and other symbols. It is basically used to provide information to the compiler on what the function does, even though its body is not available so that the compiler can do some kind of optimizations with it.
A constant function is generally defined in terms of a pure function.
A pure function is a function with basically no side effect. This
means that pure functions return a value that is calculated based on
given parameters and global memory, but cannot affect the value of any
other global variable. Pure functions cannot reasonably lack a return
type (i.e. have a void return type).
And now we can define what is a const function,
A pure function that does not access global memory, but only its
parameters, is called a constant function. This is because the
function, being unrelated to the state of global memory, will always
return the same value when given the same parameters. The return value
is thus derived directly and exclusively from the values of the
parameters given.
Here const doesn't imply anything about function mutability. But it is a function which doesn't touch global memory. You can assign normal pointers to such functions. Anyways the code region will generally ( forgetting self modifying code for a while ) be RO and you cannot modify it through the normal pointer.
Read the full insightful article here.
So when it comes to GCC Constant functions we are talking about optimizations and not function mutability.
1.What is the meaning of a pointer to a constant function versus a pointer to a non-constant function?
There is no difference between const and non-const: the function itself is not modifiable
Note: In C++ if the function is a member function of a class, const means that the state of the object within this function cannot be changed (member variables assigned to, non-const memeber functions called). In this case the const keyword is part of the member function's signature and therefore makes a difference in terms of the pointer.
2.Can a function be const?
See above.
3.Can a function be non-const (mutable)?
See above
4.What is the proper (safe) syntax for passing a function pointer?
All pointers to free functions can be cast to any other pointer to free function (i.e. their size is the same). So you could define a type for a (hypothetical) function: void f(); and convert all function pointers to this type to store. Note that you should not call the function via this common type: you need to cast it bact to its original pointer-to-function type, otherwise you get undefined behavior (and most likely crash)
For C++: pointers to member functions are not guaranteed to be convertible to pointers to free functions
1.
There is syntactically nowhere to place 'const' to make a function's contents constant.
You will run into 'function is not an l-value' error regardless if you have const or not.
typedef void (* FUNC)(void);
FUNC pFunc;
pFunc = 0; // OK
*pFunc = 0; // error: Cannot assign to a function (a function is not an l-value)
typedef void (* const FUNC)(void);
FUNC pFunc;
pFunc = 0; // error (const)
*pFunc = 0; // error: Cannot assign to a function (a function is not an l-value)
typedef void (const * FUNC)(void); // error: <cv-qualifier> (lol?)
2 & 3.
Function pointers- yes.. Function contents, doesn't look like.
4.
I don't think there is any way to make passing a function pointer safer. With all the consts in the world, the only thing you can protect is that 'SetCallback' can't change it's own local copy of the parameter.
typedef void (* const FUNC)(void);
void SetCallback(const FUNC const pCallback)
{
FUNC pTemp = pCallback; // OK (even though pTemp is not const!!)
pCallback = 0; // error (const)
}

Declaring a pointer to const or a const pointer to const as a formal parameter

I was recently making some adjustments to code wherein I had to change a formal parameter in a function. Originally, the parameter was similar to the following (note, the structure was typedef'd earlier):
static MySpecialStructure my_special_structure;
static unsigned char char_being_passed; // Passed to function elsewhere.
static MySpecialStructure * p_my_special_structure; // Passed to function elsewhere.
int myFunction (MySpecialStructure * p_structure, unsigned char useful_char)
{
...
}
The change was made because I could define and initialize my_special_structure before compile time and myFunction never changed the value of it. This led to the following change:
static const MySpecialStructure my_special_structure;
static unsigned char char_being_passed; // Passed to function elsewhere.
static MySpecialStructure * p_my_special_structure; // Passed to function elsewhere.
int myFunction (const MySpecialStructure * p_structure, unsigned char useful_char)
{
...
}
I also noticed that when I ran Lint on my program that there were several Info 818's referencing a number of different functions. The info stated that "Pointer parameter 'x' (line 253) could be declared as pointing to const".
Now, I have two questions in regards to the above. First, in regards to the above code, since neither the pointer nor the variables within MySpecialStructure is changed within the function, is it beneficial to declare the pointer as constant as well? e.g. -
int myFunction (const MySpecialStructure * const p_structure, unsigned char useful_char)
My second question is in regards to the Lint information. Are there any benefits or drawbacks to declaring pointers as a constant formal parameter if the function is not changing its value... even if what you are passing to the function is never declared as a constant? e.g. -
static unsigned char my_char;
static unsigned char * p_my_char;
p_my_char = &my_char;
int myFunction (const unsigned char * p_char)
{
...
}
Thanks for your help!
Edited for clarification -
What are the advantages of declaring a pointer to const or a const pointer to const- as a formal parameter? I know that I can do it, but why would I want to... particularly in the case where the pointer being passed and the data it is pointing to are not declared constant?
What are the advantages of declaring a pointer as a const - as a formal parameter? I know that I can do it, but why would I want to... particularly in the case where the pointer being passed and the data it is pointing to are not declared constant?
I assumed you meant a pointer to const.
By have a pointer to const as a parameter, the advantage is you document the API by telling the programmer your function does not modify the object pointed by the pointer.
For example look at memcpy prototype:
void *memcpy(void * restrict s1, const void * restrict s2, size_t n);
It tells the programmer the object pointed to by s2 will not be modified through memcpy call.
It also provides compiler enforced documentation as the implementation will issue a diagnostic if you modify a pointee from a pointer to const.
const also allows to indicate users of your function that you won't modify this parameter behind their back
If you declare a formal parameter as const, the compiler can check that your code does not attempt to modify that parameter, yielding better software quality.
Const correctness is a wonderful thing. For one, it lets the compiler help keep you from making mistakes. An obvious simple case is assigning when you meant to compare. In that instance, if the pointer is const, the compiler will give you an error. Google 'const correctness' and you'll find many resources on the benefits of it.
For your first question, if you are damn sure of not modifying either the pointer or the variable it points to, you can by all means go ahead and make both of them constant!
Now, for your Qn as to why declare a formal pointer parameter as const even though the passed pointer is not constant, A typical use case is library function printf(). printf is supposed to accept const char * but the compiler doesn't complain even if you pass a char* to it. In such a case, it makes sense that printf() doesn't not build upon the user's mistake and alter user's data inadvertantly! Its like printf() clearly telling- Whether you pass a const char * or char*, dont worry, I still wont modify your data!
For your second question, const pointers find excellent application in the embedded world where we generally write to a memory address directly. Here is the detailed explanation
Well, what are the advantages of declaring anything as a const while you have the option to not to do so? After all, if you don't touch it, it doesn't matter if it's const or not. This provides some safety checks that the compiler can do for you, and it gives some information of the function interface. For example, you can safely pass a string literal to a function that expects a const char *, but you need to be careful if the parameter is declared as just a char *.

What are some practical uses for const-qualified variables in C?

As has been discussed in several recent questions, declaring const-qualified variables in C (as opposed to const variables in C++, or pointers to const in C) usually serves very little purpose. Most importantly, they cannot be used in constant expressions.
With that said, what are some legitimate uses of const qualified variables in C? I can think of a few which have come up recently in code I've worked with, but surely there must be others. Here's my list:
Using their addresses as special sentinel values for a pointer, so as never to compare equal to any other pointer. For example: char *sentinel(void) { static const char s; return &s; } or simply const char sentinel[1]; Since we only care about the address and it actually wouldn't matter if the object were written to, the only benefit of const is that compilers will generally store it in read-only memory that's backed by mmap of the executable file or a copy of the zero page.
Using const qualified variables to export values from a library (especially shared libraries), when the values could change with new versions of the library. In such cases, simply using #define in the library's interface header would not be a good approach because it would make the application dependent on the values of the constants in the particular version of the library it was built with.
Closely related to the previous use, sometimes you want to expose pre-defined objects from a library to the application (the quintessential examples being stdin, stdout, and stderr from the standard library). Using that example, extern FILE __stdin; #define stdin (&__stdin) would be a very bad implementation due to the way most systems implement shared libraries - usually they require the entire object (here, FILE) to be copied to an address determined when the application is linked, and introduce a dependency on the size of the object (the program will break if the library is rebuilt and the size of the object changes). Using a const pointer (not pointer-to-const) here fixes all the problems: extern FILE *const stdin;, where the const pointer is initialized to point to the pre-defined object (which itself is likely declared static) somewhere internal to the library.
Lookup tables for mathematical functions, character properties, etc. This is the obvious one I originally forgot to include, probably because I was thinking of individual const variables of arithmetic/pointer type, as that's where the question topic first came up. Thanks to Aidan for triggering me to remember.
As a variant on lookup tables, implementation of state machines. Aidan provided a detailed example as an answer. I've found the same concept is also often very useful without any function pointers, if you can encode the behavior/transitions from each state in terms of a few numeric parameters.
Anyone else have some clever, practical uses for const-qualified variables in C?
const is quite often used in embedded programming for mapping onto GPIO pins of a microcontroller. For example:
typedef unsigned char const volatile * const tInPort;
typedef unsigned char * const tOutPort;
tInPort my_input = (tInPort)0x00FA;
tOutPort my_output = (tOutPort)0x00FC;
Both of these prevent the programmer from accidentally changing the pointer itself which could be disastrous in some cases. The tInPort declaration also prevents the programmer from changing the input value.
Using volatile prevents the compiler from assuming that the most recent value for my_input will exist in cache. So any read from my_input will go directly to the bus and hence always read from the IO pins of the device.
For example:
void memset_type_thing(char *first, char *const last, const char value) {
while (first != last) *(first++) = value;
}
The fact that last can't be part of a constant-expression is neither here nor there. const is part of the type system, used to indicate a variable whose value will not change. There's no reason to modify the value of last in my function, so I declare it const.
I could not bother declaring it const, but then I could not bother using a statically typed language at all ;-)
PC-lint warning 429 follows from the expectation that a local pointer to an allocated object should be consumed
by copying it to another pointer or
by passing it to a "dirty" function (this should strip the "custodial" property of the pointer) or
by freeing it or
by passing it up the caller through a return statement or a pass-by-pointer parameter.
By "dirty" I mean a function whose corresponding pointer parameter has a non-const base type. The description of the warning absolves library functions such as strcpy() from the "dirty" label, apparently because none of such library functions takes ownership of the pointed object.
So when using static analysis tools such as PC-lint, the const qualifier of parameters of called functions keeps locally allocated memory regions accounted.
const can be useful for some cases where we use data to direct code in a specific way. For example, here's a pattern I use when writing state machines:
typedef enum { STATE1, STATE2, STATE3 } FsmState;
struct {
FsmState State;
int (*Callback)(void *Arg);
} const FsmCallbacks[] = {
{ STATE1, State1Callback },
{ STATE2, State2Callback },
{ STATE3, State3Callback }
};
int dispatch(FsmState State, void *Arg) {
int Index;
for(Index = 0; Index < sizeof(FsmCallbacks)/sizeof(FsmCallbacks[0]); Index++)
if(FsmCallbacks[Index].State == State)
return (*FsmCallbacks[Index].Callback)(Arg);
}
This is analogous to something like:
int dispatch(FsmState State, void *Arg) {
switch(State) {
case STATE1:
return State1Callback(Arg);
case STATE2:
return State2Callback(Arg);
case STATE3:
return State3Callback(Arg);
}
}
but is easier for me to maintain, especially in cases where there's more complicated behavior associated with the states. For example, if we wanted to have a state-specific abort mechanism, we'd change the struct definition to:
struct {
FsmState State;
int (*Callback)(void *Arg);
void (*Abort)(void *Arg);
} const FsmCallbacks[] = {...};
and I don't need to modify both the abort and dispatch routines for the new state. I use const to prevent the table from changing at runtime.
A const variable is useful when the type is not one that has usable literals, i.e., anything other than a number. For pointers, you already give an example (stdin and co) where you could use #define, but you'd get an lvalue that could easily be assigned to. Another example is struct and union types, for which there are no assignable literals (only initializers). Consider for instance a reasonable C89 implementation of complex numbers:
typedef struct {double Re; double Im;} Complex;
const Complex Complex_0 = {0, 0};
const Complex Complex_I = {0, 1}; /* etc. */
Sometimes you just need to have a stored object and not a literal, because you need to pass the data to a polymorphic function that expects a void* and a size_t. Here's an example from the cryptoki API (a.k.a. PKCS#11): many functions require a list of arguments passed as an array of CK_ATTRIBUTE, which is basically defined as
typedef struct {
CK_ATTRIBUTE_TYPE type;
void *pValue;
unsigned long ulValueLen;
} CK_ATTRIBUTE;
typedef unsigned char CK_BBOOL;
so in your application, for a boolean-valued attribute you need to pass a pointer to a byte containing 0 or 1:
CK_BBOOL ck_false = 0;
CK_ATTRIBUTE template[] = {
{CKA_PRIVATE, &ck_false, sizeof(ck_false)},
... };
They can be used for memory-mapped peripherals or registers that cannot be changed by user code, only some internal mechanism of the microprocessor. Eg. on the PIC32MX, certain registers indicating program state are qualified const volatile - so you can read them, and the compiler won't try to optimise out, say, repeated accesses, but your code cannot write to them.
(I don't any code to hand, so I can't cite a good example right now.)

Resources