G4143
Registered Member
- Jan 16, 2019
- 68
- 31
I've been programming for several years and for the first few I always discounted the lowly constant qualifier. I would write code similar to this over-simplified C example.
Now the above code will produce the correct answers but it isn't as tight as it should be. A better C solution would be:
Now the question is. Why is the second solution better? Its better because we aren't modifying the inputs to addIt! We are notifying the compiler and user that x and y won't change. Its better documentation and may produce a more efficient binary! All good.
Now the question is. How often should I/you consider the constant qualifier? At first I thought it was a silly thing to consider until I started exploring functional programming where the norm is immutable data(constant data). In functional programming, you can write entire programs and libraries where all the data is constant.. In our C example it would look like this..
Now everything is constant and most people are still not convinced of its usefulness...
The constant qualifier has one more 'undeniable' benefit. The data doesn't change so its easy to reason about. An example will demonstrate this point..
Say we have two variables in a program.
Now we start this program with a debugger and monitor these two variables... Time passes and code executes...
What's the value of x?
What's the value of y?
Yeah its simple to predict what x is because its constant!
Its impossible to predict what y is because its mutable. We have to query its value each time we want it and we may not even know how that value is generated. Constant data does have this one feature that's very beneficial in large programs..
So do you ever consider the constant qualifier or use constant data in your programs?
Here's an example of a simple C linked list that embraces the constant qualifier. Notice that just about everything is qualified with const.
node.c
node.h
main.c
Once you start writing programs that embrace the constant qualifier, you'll find you are putting that qualifier everywhere.
Hope you enjoyed my first post... G4143
Any questions or gripes! Please post them.
Code:
int addIt (int x, int y) {
return x + y;
}
Now the above code will produce the correct answers but it isn't as tight as it should be. A better C solution would be:
Code:
int addIt (const int x, const int y) {
return x + y;
}
Now the question is. How often should I/you consider the constant qualifier? At first I thought it was a silly thing to consider until I started exploring functional programming where the norm is immutable data(constant data). In functional programming, you can write entire programs and libraries where all the data is constant.. In our C example it would look like this..
Code:
const int addIt (const int x, const int y) {
return x + y;
}
The constant qualifier has one more 'undeniable' benefit. The data doesn't change so its easy to reason about. An example will demonstrate this point..
Say we have two variables in a program.
Code:
const int x = 4143;
int y = 1234;
What's the value of x?
What's the value of y?
Yeah its simple to predict what x is because its constant!
Its impossible to predict what y is because its mutable. We have to query its value each time we want it and we may not even know how that value is generated. Constant data does have this one feature that's very beneficial in large programs..
So do you ever consider the constant qualifier or use constant data in your programs?
Here's an example of a simple C linked list that embraces the constant qualifier. Notice that just about everything is qualified with const.
node.c
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
struct node {
const int x;
const struct node * const next;
};
static const struct node empty = {INT_MIN, NULL};
const struct node * const createEmptyNodes(void) {
return ∅
}
const struct node * const addNode(const int x, const struct node * const tail) {
void *vptr = malloc(sizeof(const struct node));
if (vptr) {
const struct node temp = {x, tail};
memcpy(vptr, &temp, sizeof(const struct node));
}
return vptr;
}
const struct node * const addArrNode(const int * iptr, const size_t size, const struct node * const tail) {
if (size > 0) {
return addArrNode((iptr + 1), (size - 1), addNode(*iptr, tail));
}
return tail;
}
void displayNodes(const struct node * const nodes) {
if (nodes->next) {
fprintf(stdout, "%d\n", nodes->x);
displayNodes(nodes->next);
}
}
void freeNodes(const struct node * const nodes) {
if (nodes->next) {
freeNodes(nodes->next);
free((void*)nodes);
}
}
Code:
#ifndef NODE_H_
#define NODE_H_
struct node {
const int x;
const struct node * const next;
};
const struct node * const createEmptyNodes(void);
const struct node * const addNode(const int x, const struct node * const tail);
const struct node * const addArrNode(const int *, const size_t, const struct node * const);
void displayNodes(const struct node * const nodes);
void freeNodes(const struct node * const nodes);
#endif
Code:
#include <stdio.h>
#include "node.h"
#define ARR_SIZE 10
int main (int argc, char ** argv) {
int arr[ARR_SIZE] = {10, 1, 9, 2, 8, 3, 7, 4, 6, 5};
const struct node * const node1 = createEmptyNodes();
const struct node * const node2 = addNode(4143, node1);
const struct node * const node3 = addNode(8888, node2);
const struct node * const node4 = addArrNode(arr, ARR_SIZE, node3);
displayNodes(node4);
freeNodes(node4);
return 0;
}
Once you start writing programs that embrace the constant qualifier, you'll find you are putting that qualifier everywhere.
Hope you enjoyed my first post... G4143
Any questions or gripes! Please post them.