C99 tricks
blog.noctua-software.com
blog.noctua-software.com
That said, I'm rather sceptical towards it, I think it's better written as-is.
Otherwise, the question "does SIZE mean bytes, or number of elements?" always arises to haunt me. Once you need to keep looking stuff like that up, the macro isn't helping.
In actual code, the name of the array never needs to be enclosed in parentheses so it's often clearer too. E.g. something like:
int fourk[4096];
for(size_t i = 0; i < sizeof fourk / sizeof *fourk; ++i)
...
I realize that it's not 100% DRY to repeat the array name, but I think it's a small price to pay for not having to use a non-standard macro that requires learning. It's all about friction.Come to think of it, I'm afraid I'm leaving a time bomb for the next inexperienced maintainer who doesn't know the limitations.
Even better, grab it from CCAN: http://ccodearchive.net/info/array_size.html
Cheers, Rusty.
I see you use __builtin_types_compatible_p, which looks very useful but also appears to be a GCC-specific.
(I had to enable JS to see the comments, and that caused me to see the very same effect reported in the first comment)
If that's true, blaming fabric of the web for this is ridiculous. Blame idiots who went ahead with 'sanctions' on information.
Oh, and by the way, why not use X macros in the form where the macro to apply is passed as the argument? #define SPRITES(S) S(1, 2, 3) S(2, 3, 4) etc.
gcc -std=c99 -pedanticThe issue that was called out, however, was the use of "FOO(x, ## __VA_ARGS__)".
GNU C has an extension that causes the ',' to be removed if __VA_ARGS__ is empty. AFAIK, it is not standard.
C99: http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf (post-publication ‘draft’ including technical corrigenda 1–3)
C11: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf (final draft as voted on)
Similarly for C++:
C++11: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n333...
C++14: http://open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.pd...
Who has written C99 in the last 24h within a larger project and if yes what kind of project?
I work on embedded software for industrial assembly tools.
The existing Python implementation then helps with debugging and testing.
Compilation times, no need for inheritance and the fact that most libraries I'm using are written in C were the reasons I chose C over C++ or something else.
const char *lookup[] = {
[0] = "ZERO",
[1] = "ONE",
[4] = "FOUR"
};
assert(strcmp(lookup[0], "ZERO") == 0);
(not available in C++ or pre-C99) enum fields = { x, y, z };
int point[] = {
[x] = 1,
[y] = 2,
[z] = 3
};
This is used pretty extensively in the QEMU codebase, which is where I first learned it.What is the advantage of this:
#define min(a, b) ({ \
__typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; \
})
over the naive #define min(a, b) (((a) < (b)) ? (a) : (b))
? min(a++, b++);
a or b would really be incremented twice.A compiler might be able to avoid this if it can prove expensive_calcluation is pure, but this is usually not done unless WPO is in play.
(void) (&_a == &_b); \
… which makes sure that the types are actually compatible, and not just having one converted to the other.If someone uses this switch macro in a codebase I am working on, I'll most probably punch them in the face.
Also look up GL_ARB_debug_output - https://www.opengl.org/registry/specs/ARB/debug_output.txt. I don't remember this ever telling me anything terribly useful for debugging, but I did get a couple of perf hints from it... anyway, it's vendor-specific, so on OS X, maybe it will help.
(BTW - if you ever end up using Direct3D on Windows, be sure to activate the debug runtime. Compare and contrast.)
Apparently Apple is unaware of this technique...
There are exceptions to this general rule, and sometimes you do need to use glGetError in the normal run of things, and take action based on the result. But they are very much exceptions.
#define GLSL(str) (char*)"#version 330\n" #str
It basically enables you to embed quick snippets of GLSL inside your C code, instead of using concatenated strings. Example: char* fragShader = GLSL(
in vec3 uv;
out vec4 color;
uniform sampler2DArray tex;
void main()
{
// Comments work too
color = texture(tex, uv);
}
);
In Sublime Text you even get code completion and color highlighting, since GLSL and C look so alike.I believe it might work for OpenCL Kernels too.
The only downside is that it doesn't add line breaks by itself (hence the "#version 330\n", which requires a line break), so GLSL Compilation errors aren't as useful.
(Source: https://open.gl/geometry )
// Instead of x = x ? x : 10;
// We can use the shorter form: x = x ?: 10;
#define min(a, b) ({ \ __typeof__ (a) _a = (a); \ __typeof__ (b) _b = (b); \ _a < _b ? _a : _b; \ })
Ex. ARRAY_SIZE works by simply using 'sizeof' to find the size of the array. This only works if the array was defined earlier in the same section of code though, it doesn't work on say, arrays passed to functions. So the name 'ARRAY_SIZE' for this macro is misleading because it only works on some arrays in some instances. Anybody who's programmed in C would know this, but they could probably write their own macro to do this anyway. It's beginners who wouldn't know how to write this macro, and would also be confused by how it works.
The thing you might consider standardizing is the GNU extensions that they used in this article, naming ({ }) and typeof. Both can be handy honestly, but C11 doesn't standardize either IIRC.
Here's a handy table showing GCC's support: https://gcc.gnu.org/wiki/C11Status.
I'm pretty sure Clang supports C11 well too, didn't find a corresponding table though. It says "By default, Clang builds C code in GNU C11 mode [...]" on this page: http://clang.llvm.org/compatibility.html.
http://blog.smartbear.com/codereviewer/c11-a-new-c-standard-...
sizeof(mytype *) / sizeof(mytype)
which will usually be 0 or 1 (most of my arrays hold at least words.) #include <stdio.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
void p (int* a) {
printf("ARRAY_SIZE of arr = %lu, %lu, %lu\n", ARRAY_SIZE(a), sizeof(a), sizeof((a)[0]));
}
int main () {
int arr [] = {0, 1, 2, 3, 4};
printf("ARRAY_SIZE of arr = %lu, %lu, %lu\n", ARRAY_SIZE(arr), sizeof(arr), sizeof((arr)[0]));
p(arr);
}
prints:ARRAY_SIZE of arr = 5, 20, 4
ARRAY_SIZE of arr = 2, 8, 4
where in the function, the arr has decayed into a pointer losing the additional info about size (now the size of a pointer 8bytes or 64bits on my host). Which is why you usually get the length of the array before invoking the function and pass it in as additional information, or wrap the complete array in a struct to preserve sizeof info (http://spin.atomicobject.com/2014/03/25/c-single-member-stru...).
(A && B) || (A && !B) == A,
but what he means by A on the RHS, I think, is that you must take into account the fact that A_LHS might be zero. You can't really write this identity and give a constant on the right, so he wrote the next best thing.Well, the real next best thing would be !(!A).