This is a compilation of the C language programming tips I posted on the Fediverse during 2022:
The elvis operatorhttps://triptico.com/social/angel/p/1673265846.832608
If you program in C, you've probably used what is called the ternary operator a million times in expressions like this:
value = user_value ? user_value : default_value;
Where you test
user_value and, if it's non-zero, you store it in
value; otherwise, you set
What you may not know is that, thanks to a gcc (and others) extension, you can abridge that expression to this:
value = user_value ?: default_value;
This ?: thing is colloquially named the 'Elvis' operator (if you don't see why, just look at it with you head slightly slanted to the left).https://en.wikipedia.org/wiki/Elvis_operator
TIL that there is something named linker optimization that forces the deletion of unused functions in your final executable. As a bonus, you get the list of unused functions as compiler warnings (dead code is always bad, so you get the change to delete them or comment them out).
If you have a standard build system, do the following:
make CFLAGS="-ffunction-sections -fdata-sections" LDFLAGS="-Wl,--gc-sections -Wl,--print-gc-sections"
Concatenated PPM images as a video streamhttps://triptico.com/social/angel/p/1671347271.960902
TIL that most video processing tools accept as a valid input stream a set of concatenated PPM  files, so you can generate video from your own programs easily. You just have to pipe your program's output to the appropriate tools (indicating the FPS) like
./fancy-prg | mpv --no-correct-pts --fps=$FPS -
./fancy-prg | ffmpeg -i - -r $FPS video.mp4https://en.wikipedia.org/wiki/Netpbm_format
Full paths in shared libraries' sonamehttps://triptico.com/social/angel/p/1667714202.685173
TIL that you can have a full-path
soname in a dynamic library, so that binaries linked to it can find it even if it's in a non-standard place:
gcc -shared -o libcrazy.so -Wl,-soname,/an/esoteric/place/to/store/libcrazy.so crazy.c gcc -o main -L. -lcrazy main.c
This way, you don't need kludges regarding the use of
LD_LIBRARY_PATH nor anything else.
Executing hand-crafted machine codehttps://triptico.com/social/angel/p/1667464895.428412
If you want to create an executable program in memory and execute it without going through the filesystem, this is how you do it (Linux only):
int fd = memfd_create("foo", MFD_CLOEXEC); // write your image to fd however you want fexecve(fd, argv, envp);https://unix.stackexchange.com/questions/230472/can-i-exec-an-entirely-new-process-without-an-executable-file
Finding memory leakshttps://triptico.com/social/angel/p/1667328755.759676
If you develop in C, you'll probably end up using memory leak detection tools like
libleak or the
scan-build tool from the LLVM compiler. There is a less known tool inside the GCC compiler itself: the
If you use a standard make setup, you can recompile your project doing
make CFLAGS="-fsanitize=address -fno-omit-frame-pointer"
After exiting your program, a summary of memory leak errors (including the line of the source code were it happened) will be printed out.
Poor man's profilerhttps://triptico.com/social/angel/p/1665694300.323309
Poor man's profiler, or profiling a running program with a cheap combination of gdb, awk and scripting:
Sampling tools like oprofile or dtrace's profile provider don't really provide methods to see what [multithreaded] programs are blocking on - only where they spend CPU time. Though there exist advanced techniques (such as systemtap and dtrace call level probes), it is overkill to build upon that [...]
[...] one needs to improvise, like.. use debuggers - they can walk threads and provide stacks.
Fast character case conversionhttps://triptico.com/social/angel/p/1666985574.734641
Fast character case conversion (or how to really compress sparse arrays):
Converting strings and characters between lower and upper cases is a very common need.
In particular, case conversion is often used to implement case-insensitive comparision, an operation that is often present on the program's fast paths as a part of data container lookups and content manipulation.
So it is usually desirable to make case conversions as fast as possible.
In this post we are going to look at one of the options - very fast case conversion using compressed lookup tables and also at some options for compressing these even further.
TIL by accident that you can type
make from inside gdb and does what you think it does.
Modern C for C++ Peepshttps://triptico.com/social/angel/p/1673121099.281843
I find the article interesting not only for C++ "peeps", but for us greybeard C programmers as well, who learnt the language in the eighties. Remarkable sections in the document are:
- Use struct wrappers for strong typing (I've never done this, but it's interesting; accessing the components inside the structs may become a bit tedious, though).
- Initialization in C99 (I haven't used this to its full potential).
- Don’t be afraid to pass and return structs by value (as an old fart, I always pass pointers to structs, and this section reasons otherwise for small structs).
- Named optional arguments (or, as the author more accurately describes this, the "option bag").