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 | #ifndef __dbg_h__ #define __dbg_h__ #include <stdio.h> #include <errno.h> #include <string.h> #ifdef NDEBUG #define debug(M, ...) #else #define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) #endif #define clean_errno() (errno == 0 ? "None" : strerror(errno)) #define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) #define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) #define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d) " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) #define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } #define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } #define check_mem(A) check((A), "Out of memory.") #define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; } #endif |
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 | #undef NDEBUG #ifndef _minunit_h #define _minunit_h #include <stdio.h> #include <dbg.h> #include <stdlib.h> #define mu_suite_start() char *message = NULL #define mu_assert(test, message) if (!(test)) { log_err(message); return message; } #define mu_run_test(test) debug("\n-----%s", " " #test); \ message = test(); tests_run++; if (message) return message; #define RUN_TESTS(name) int main(int argc, char *argv[]) {\ argc = 1; \ debug("----- RUNNING: %s", argv[0]);\ printf("----\nRUNNING: %s\n", argv[0]);\ char *result = name();\ if (result != 0) {\ printf("FAILED: %s\n", result);\ }\ else {\ printf("ALL TESTS PASSED\n");\ }\ printf("Tests run: %d\n", tests_run);\ exit(result != 0);\ } int tests_run; #endif |
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 | #include "minunit.h" #include "math.h" #define KISS_VEC_IMP #include "kiss_vec.h" #define EPSILON 0.000001f #define EQ(a,b) (fabs((a) - (b)) < EPSILON) char* test_vec_add() { vec v0 = vec3( 1.0f, 2.0f, 3.0f ); vec v1 = vec3( 2.0f, 3.0f, 5.0f ); vec_add( &v0, &v0, &v1 ); mu_assert( EQ( v0.x, 3.0f ), "x not equal" ); mu_assert( EQ( v0.y, 5.0f ), "y not equal" ); mu_assert( EQ( v0.z, 8.0f ), "z not equal" ); return NULL; } char *all_tests() { mu_suite_start(); mu_run_test(test_vec_add); return NULL; } RUN_TESTS(all_tests); |
1 | #define COMMAND(name) void name(int argc, const char* argv[]) |
1 2 3 4 5 6 7 | // declaration COMMAND(do_something); // definition COMMAND(do_something) { // code } |
1 | typedef COMMAND(Command); |
GreenLightning
I like the function signature macro which I learned from Casey's Working on The Witness blog series (see section Filter Tables of part 15). It is useful if you have a bunch of functions with the same signature. For example a command line utility I wrote has a function for each command the user can issue. The main function reads in the first argument and calls the appropriate function for that command with the remaining arguments. The macro itself looks like this:
1 #define COMMAND(name) void name(int argc, const char* argv[])
To create a new command:
1 2 3 4 5 6 7 // declaration COMMAND(do_something); // definition COMMAND(do_something) { // code }
If you need to deal with function pointers, you can also do this:
1 typedef COMMAND(Command);
This means that the function prototype is only defined in the macro and all the declarations and definitions automatically match. If I wanted to add another argument, I would only need to change the macro and the calls in the main function. Also, if I want to create a new command, I just need to write COMMAND(do_something_else) and don't have to remember the exact prototype.
1 2 3 4 5 6 7 8 9 | #ifdef __cplusplus # define scast(t, v) static_cast<t>(v) # define rcast(t, v) reinterpret_cast<t>(v) # define ccast(t, v) const_cast<t>(v) #else # define scast(t, v) ((t)(v)) # define rcast(t, v) ((t)(v)) # define ccast(t, v) ((t)(v)) #endif |
1 2 3 4 5 6 7 8 | #define CAT_2_TOKENS_2(A, B) A ## B #define CAT_2_TOKENS(A, B) CAT_2_TOKENS_2(A, B) #ifndef __cplusplus #define static_assert(condition, message) \ typedef struct { int CAT_2_TOKENS(static_assertion_failure__, message) : !!(condition); } \ CAT_2_TOKENS(static_assertion_, __COUNTER__) #endif |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #if defined(_MSC_VER) && !defined(__clang__) # define PUSH_PACK(V) __pragma(pack(push, V)) # define POP_PACK __pragma(pack(pop)) # define PUSH_WARNING __pragma(warning(push)) # define POP_WARNING __pragma(warning(pop)) # define PUSH_WARNING_LEVEL(V) __pragma(warning(push, V)) # define DISABLE_MSVC_WARNING(V) __pragma(warning(disable: V)) # define DISABLE_LLVM_WANRING(V) #else # define DO_PRAGMA(X) _Pragma(#X) # define PUSH_PACK(V) DO_PRAGMA(pack(push, V)) # define POP_PACK(V) DO_PRAGMA(pack(pop)) # define PUSH_WARNING DO_PRAGMA(GCC diagnostic push) # define POP_WARNING DO_PRAGMA(GCC diagnostic pop) # define PUSH_WARNING_LEVEL DO_PRAGMA(GCC diagnostic push V) # define DISABLE_MSVC_WARNING(V) # define DISABLE_LLVM_WARNING(V) DO_PRAGMA(GCC diagnostic ignored #V) #endif |
ratchetfreak
For rcast you could do something like *((t*)((void*)(&(v))))
cubercaleb
i am not sure you understand the point of reinterpret_cast (or the problem this is trying to solve), which is used for converting pointers to other pointers, and for converting pointers to integers and vis versa. It is not the same thing as taking a reference, doing a pointer cast, then doing a dereference.
The motivation behind these macros is that on the highest possible warning levels (-Wall -Wpedantic -Wextra -Werror) on clang, using c style casts is prohibited, and instead they want you to use static/reinterpret/const cast. Since those aren't available to c and I don't want to arbitrarily disable the warning across the board I use these macros for casting. They are terse, easy to grep, display intent of the cast and they work in both c/c++.
ratchetfreak
But reinterpret_cast as defined by C++ must be able to roundtrip as long as all the intermediate types used are large enough to hold it. That's what my comment was about. If you introduce this to other C++ programmers they will expect rcast to follow those rules.
rcast(float32, rcast(int32, myFloat32)) under the original C definition will not preserve the float while the C++ definition will.
1 | *reinterpret_cast<uint32_t*>(&my_float) |
1 2 3 4 5 6 7 | uint32_t FloatBitsToUint32(float Value) { return(*rcast(uint32_t *, &value)); } float Uint32ToFloatBits(uint32_t Value) { return(*rcast(float *, &value)); } |
1 2 3 4 5 6 7 8 | // NOTE(joey): This is some fucking magic vodoo macro shit I found here // http://stackoverflow.com/questions/1082192/how-to-generate-random-variable-names-in-c-using-macros #define PP_CAT(a, b) PP_CAT_I(a, b) #define PP_CAT_I(a, b) PP_CAT_II(~, a ## b) #define PP_CAT_II(p, res) res #define gp_UNIQUE_NAME(base) PP_CAT(base, __LINE__) #define gp_InfiniteLoop int gp_UNIQUE_NAME(inf_) = 1; while (gp_UNIQUE_NAME(inf_)) |
1 2 3 | gp_InfiniteLoop { // fun infinite code here } |
mojobojo
Today I wanted to have an infinite loop without generating a warning with /W4 and without suppressing the specific warning like what while(1) and for (;;) give.
iffy
As far as I'm aware, no major compiler currently issues a warning when using "for (;;)" to indicate an infinite loop. In fact, that's probably the biggest reason to prefer this syntax to something like "while (1)". What version of MSVC are you using where this is not the case?
1 2 3 4 5 6 7 | int func() { for (;;) { // do something } return 0; } |
mojobojo
for (;;) was causing an unreachable code warning in something like.
1 2 3 4 5 6 7 int func() { for (;;) { // do something } return 0; }