summaryrefslogtreecommitdiff
path: root/doc/macros.rst
blob: 752f81ea7a2af4033a5625acb2df9afb1886b9b7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
======
Macros
======

All macros in this section are available through ``#include <libHX/defs.h>``.

Preprocessor
============

.. code-block:: c

	#define HX_STRINGIFY(s)HX_STRINGIFY

Transforms the expansion of the argument ``s`` into a C string.


Sizes
=====

.. code-block:: c

	#define HXSIZEOF_Z16
	#define HXSIZEOF_Z32
	#define HXSIZEOF_Z64

Expands to the size needed for a buffer (including ``\0``) to hold the base-10
string representation of 16‑, 32‑ or 64‑bit integer (either signed or
unsigned), respectively.

Locators
========

.. code-block:: c

	output_type *containerof(input_type *ptr, output_type, member);

	size_t HXsizeof_member(struct_type, member);
	output_type HXtypeof_member(struct_type, member);

``containerof`` will return a pointer to the struct in which ``ptr`` is
contained as the given member. (In C++, it is required that the encompassing
``output_type`` has so-called "standard layout", but to date I have never found
an implementation where this matters.)

.. code-block:: c

	struct foo {
		int bar;
		int baz;
	};

	static void test(int *ptr)
	{
		struct foo *self = containerof(baz, struct foo, baz);
	}

``HXsizeof_member`` and ``HXtypeof_member`` are shortcuts (mainly for the C
language) to get the size or type of a named member in a given struct:

.. code-block:: c

	char padding[FIELD_SIZEOF(struct foo, baz)];

In C++, one can simply use ``sizeof(foo::baz)`` and ``decltype(foo::baz)``.


Array size
==========

.. code-block:: c

	size_t ARRAY_SIZE(type array[]); /* implemented as a macro */

Returns the number of elements in array. This only works with true arrays
(``type[]``), and will fail to compile when passed a pointer-to-element
(``type *``), which is often used for array access too.


Compile-time build checks
=========================

.. code-block:: c

	int BUILD_BUG_ON_EXPR(bool condition); /* implemented as a macro */
	void BUILD_BUG_ON(bool condition); /* implemented as a macro */

Causes the compiler to fail when condition evaluates to true. If not
implemented for a compiler, it will be a no-op. ``BUILD_BUG_ON`` is meant to be
used as a standalone statement, while ``BUILD_BUG_ON_EXPR`` is for when a check
is to occur within an expression, that latter of which is useful for within
macros when one cannot, or does not want to use multiple statements.

.. code-block:: c

	type DEMOTE_TO_PTR(type expr); /* macro */

Changes the type of ``expr`` to pointer type. If ``expr`` is of array type
class, changes it to a pointer to the first element. If ``expr`` is of function
type class, changes it to a pointer to the function.

.. code-block:: c

	int main(void);
	int (*fp)(void);
	char a[123];
	DEMOTE_TO_PTR(main); /* yields int (*)(void); */
	DEMOTE_TO_PTR(fp);   /* also yields int (*)(void); */
	DEMOTE_TO_PTR(a);    /* yields char * */


UNIX file modes
===============

.. code-block:: c

	#define S_IRUGO   (S_IRUSR | S_IRGRP | S_IROTH)S_IRUGO
	#define S_IWUGO   (S_IWUSR | S_IWGRP | S_IWOTH)S_IWUGO
	#define S_IXUGO   (S_IXUSR | S_IXGRP | S_IXOTH)S_IXUGO
	#define S_IRWXUGO (S_IRUGO | S_IWUGO | S_IXUGO)S_IRWXUGO

The defines make it vastly easier to specify permissions for large group of
users. For example, if one wanted to create a file with the permissions
``rw-r--r--`` (ignoring the umask in this description), ``S_IRUSR | S_IWUSR``
can now be used instead of the longer ``S_IRUSR | S_IWUSR | S_IRGRP |
S_IROTH``.


VC runtime format specifiers
============================

The Microsoft Visual C runtime (a weak libc) uses non-standard format
specifiers for certain types. Whereas C99 specifies ``z`` for ``size_t`` and
``ll`` for ``long long``, MSVCRT users must use ``I`` and ``I64`` (forming
``%Id`` instead of ``%zd`` for ``ssize_t``, for example). libHX provides two
convenience macros for this:

.. code-block:: c

	#define HX_SIZET_FMT    "z" or "I"HX_SIZET_FMT
	#define HX_LONGLONG_FMT "ll" or "I64"HX_LONGLONG_FMT

These may be used together with ``printf`` or ``scanf``:

.. code-block:: c

	printf("struct timespec is of size %" HX_SIZET_FMT "u\n",
	       sizeof(struct timespec));

Take note that mingw-w64's libc *does* adhere to POSIX and so, %z can be used.