Correct me if I am wrong, declaring formal parameters to functions as const, if they should not be/is not changed, has 2 benefits;
1. It tells the program that calls this function that the parameter will not be changed - so don't worry.
2. It tells the implementor and the maintainer of this function that the parameter should not be changed inside the function. And it is for this reason that some people advocate that it is a good idea to const-ify even a non-pointer parameter:
void my_func(const int i) { ... }
because if the original programmer or a subsequent maintainer accidentally change the value of the parameter, the compiler can catch it.
A third benefit may be that the compiler can optimize the program if it knows for sure that the parameter is not changed inside the function. I am not sure about this though.
Now, I would like to benefit from the const-ification of the function parameter. Let's say I have this:
Code:
typedef struct s_fifoItem t_fifoItem;
struct s_fifoItem {
t_fifoItem *next;
t_fifoItem *prev;
void *elem;
};
typedef t_fifoItem t_fifoQueue;
void enqueue(t_fifoQueue *q, void *elem)
{
t_fifoItem *i, *last;
i = (t_fifoItem *) malloc(sizeof(t_fifoItem));
i->elem = elem;
last = q->prev;
last->next = i;
i->next = q;
q->prev = i;
}
elem appears to be a good candidate for const-ification. Intutitively the program calling enqueue() normally does not expect that the item to be enqueued is to be changed. And the implementor of enqueue() would not want to change elem either; and actually elem is not changed in the above implementation. But if I const-ify elem, gcc would complain (in a warning) that the assignment
i->elem = elem;
would discard the const qualifier because the type of "i->elem" is "void *", not "const void *". One solution is to cast away the const-ness of elem in that assignment:
i->elem = (void *)elem;
Another solution is to change the declaration of elem in struct s_fifoItem to be:
const void *elem;
The latter solution is not practical because there are other places that will change *elem.
However, the former solution of casting away the const-ness is not very appealing. It is kind of cheating.
So, how do people resolve this? And to a deeper level, gcc seems to be caught bewteen 2 conflicting goals: ensuring type correctness (a double cannot be assigned to an int, a const void * cannot be assigned to a void *, etc) and ensuring the unmodifiability of a variable. From the point of view of language design, what are the issues involved and how do other programming languages deal with it?