“the () in macros is like a condom basically”

— Unknown

Cool tricks in the C programming language.

The only reasons these tricks exist is because C is shitty and old. The tricks are still cool, though.

1. Sized enum macro

#include <stdio.h>
#include <stdint.h>

#define ENUM(type, name) type name; enum

typedef ENUM(uint8_t, Thing) {
	THING_FOO,
	THING_BAR,
	THING_BAZ,
};

struct State {
	Thing thing;
	/* ... */
};

int main() {
	printf("%zu\n", sizeof(Thing)); // 1
	return 0;
}

2. Inline shader code

#include <stdio.h>

#define SHADER(...) #__VA_ARGS__

const char *shader = SHADER(
	\x23version 330 core\n
	
	void main() {
		gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
	}
);

int main() {
	printf("%s\n", shader); // #version 330 core
	                        //  void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); }
	return 0;
}

3. Optional function parameters

C macro approach to using optional / default / named function params, using struct designated initializers.
Mandatory values are passed first as standard function params (rect in the example).
Especially useful when a zero value can be made a valid value.

typedef struct {
	Point pivot;
	float scale;
	float angle;
	bool clip;
} Transform_Opt;

void transform_opt(Rect rect, Transform_Opt opt) {
	/* ... */
}

#define transform(rect, ...) transform_opt((rect), (Transform_Opt){ .scale = 1.0, __VA_ARGS__ })

int main() {
	/* ... */
	transform(rect);
	transform(rect, .scale = 0.5);
	transform(rect, .angle = 90.0, .clip = true);
	transform_opt(rect, opt);
	
	return 0;
}

4. Type only passable by a pointer

#include <assert.h>

typedef char foo[1]; // Defines a type foo that is impossible to pass by value...

void bar(foo x) // ...because an array decays to a pointer here.
{
	assert(sizeof(x) == 8);
}

int main()
{
	foo x;
	assert(sizeof(x) == 1);
	bar(x);
	
	return 0;
}