From 63d776b9d6afd037bd115dc365b2dffd5e699991 Mon Sep 17 00:00:00 2001 From: Nicolas Dato Date: Wed, 26 Mar 2025 15:14:00 -0300 Subject: new article, using typedef or not --- zola/content/articles/safer-pointers.md | 6 ++-- zola/content/articles/typedef-or-not.md | 55 ++++++++++++++++++++++++++++++--- 2 files changed, 54 insertions(+), 7 deletions(-) (limited to 'zola/content/articles') diff --git a/zola/content/articles/safer-pointers.md b/zola/content/articles/safer-pointers.md index 1a1b55e..d6fd418 100644 --- a/zola/content/articles/safer-pointers.md +++ b/zola/content/articles/safer-pointers.md @@ -14,10 +14,10 @@ Tags=["C", "Patterns", "Pointers"] Pointers are an important feature of C, but at the same time they are prone to error. To reduce errors, and make them safer to use, I propose the following 4 tips: -1. Encapsulating the *malloc()* and *free()* functions +1. Encapsulating the *malloc()* and *free()* functions. 2. Using *calloc()* in the new alloc function, and making the structure "fail-safe" when everything is zero. -3. Making the new *free* function set the freed pointer to *NULL* -4. Every time a pointer is passed to another function, deciding who *owns* the pointer +3. Making the new *free* function set the freed pointer to *NULL*. +4. Every time a pointer is passed to another function, deciding who *owns* the pointer. ### Example diff --git a/zola/content/articles/typedef-or-not.md b/zola/content/articles/typedef-or-not.md index 9903d96..8a70f77 100644 --- a/zola/content/articles/typedef-or-not.md +++ b/zola/content/articles/typedef-or-not.md @@ -1,11 +1,58 @@ +++ title = "Using typedef or not" -description = "TODO" -date = 2024-12-20 -draft = true +description = "When to use typedef and why" +date = 2025-03-26 authors = ["Nicolás Dato"] [taxonomies] -Tags=["C"] +Tags=["C", "Patterns"] +++ +## General Idea + +Using *typedef* allows us to rename a data type, and I follow these ideas: +- Sticking to the current coding convention. +- Using *typedef* for encapsulated structs (i.e. hidden, opaque). +- Using it for function pointers. +- Avoiding it for any other case, including normal structs and enums. + +### Example + +```C +/* The .h file */ +struct position { + int x; + int y; +}; + +typedef struct ctx ctx; + +typedef int (*context_cb)(ctx *ctx, struct position *position); + +ctx *new_context(context_cb cb); +``` + +```C +/* The .c file */ + +struct ctx { + context_cb cb; + /*...*/ +}; +``` + +## Explanation + +I kind of avoid *typedef*, the main problem I see is that it hides the actual type. +However, if you have an encapsulated struct then it makes sense to hide it, +because you can't use it as a struct. + +I prefer to know that the type is an enum, or an struct. This way, when it is an +struct I know that I can access its elements, and that doing it should be safe. +If the struct is meant to be accessed only by functions, then it should be +opaque and typedef should be used. + +Also, it allows you to use the same name for related things, +like [stat](https://www.man7.org/linux/man-pages/man2/stat.2.html) +that is a function and also the struct used in that function. + -- cgit v1.2.3