

0 / 2 embers
0 / 3000 xp
click for more info
Complete a lesson to start your streak
click for more info
Difficulty: 6
click for more info
Not enough gems
Cost: 6 gems
1: Pointer-Pointers
incomplete
2: Array of Pointers
incomplete
3: Void Pointers
incomplete
4: Swapping Integers
incomplete
5: Swapping Strings
incomplete
6: Generic Swap
incomplete
This lesson's interactive features are locked, please to keep using them
We've already discussed void, which essentially means "nothing" in C. It's used in a few different contexts:
void update_soldier(soldier_t *s): means the function returns nothingsoldier_t new_soldier(void): means the function takes no arguments.And, because C likes re-using ideas but with slightly different meanings (the genius of the design can't be understood by us mere mortals) void also has another use!
A void * "void pointer" tells the compiler that this pointer could point to anything. This is why void pointers are also known as a "generic pointer". Since void pointers do not have a specific data type, they cannot be directly dereferenced or used in pointer arithmetic without casting them to another pointer type first.
Casting to and from void pointers in C is unique because void pointers are type-agnostic. When casting a specific type pointer to a void pointer, no type information is retained, allowing the void pointer to point to any data type. However, you must cast a void pointer back to its original type before dereferencing it, as direct dereferencing is not possible.
int number = 42;
void *generic_ptr = &number;
// This doesn't work
printf("Value of number: %d\n", *generic_ptr);
// This works: Cast to appropriate type before dereferencing
printf("Value of number: %d\n", *(int*)generic_ptr);
A common pattern is to store generic data in one variable, and the type of that data in another variable. This is useful when you need to pass data around without knowing its type at compile time.
typedef enum DATA_TYPE {
INT,
FLOAT
} data_type_t;
void printValue(void *ptr, data_type_t type) {
if (type == INT) {
printf("Value: %d\n", *(int*)ptr);
} else if (type == FLOAT) {
printf("Value: %f\n", *(float*)ptr);
}
}
int number = 42;
printValue(&number, INT);
float decimal = 3.14;
printValue(&decimal, FLOAT);
In Sneklang, we have to dynamically interpret Snek code and store the values in memory. The snek_object_kind_t enum defines the different types of objects that can be stored in memory.
Complete the snek_zero_out function. It accepts a generic pointer to one of:
snek_int_tsnek_float_tsnek_bool_tIt should "zero out" the .value field of the struct by setting it to the zero value of its type. Use the kind parameter to figure out which type of struct you are working with.
When working with pointers and dereferencing them, parentheses usage is essential. Consider the following examples:
((some_struct_t*)ptr)->field means casting is applied to ptr and then the field is obtained.(some_struct_t*)ptr->field means casting is applied to ptr->field.