I am a bit rusty, but isn't it always better to individually parenthesize macro variables in the expression?<p><pre><code> #define CHECK(X, Y) \
do { printf("Performing Assertion\n"); assert((X - Y) != 0); \
printf("Assertion passed\n"); } while (0)
</code></pre>
Here, assert((X - Y) != 0) should be assert(((X) - (Y)) != 0)<p>It's OK when you are doing subtraction, but if you were doing something like division or multiplication, you could screw with the order of operations if you don't do this.
I wish this article talked about why people choose to do and not do these things.<p>So much of this stuff is the kind of thing people new to C should not be doing. Minimizing use of preprocessor directives leads to more maintainable C. Use them where they are needed and not anywhere else.<p>Also, for the swapping they show:<p><pre><code> a = a ^ b;
b = a ^ b;
a = a ^ b;
</code></pre>
They fail to point out it's (platform dependent) performance implications. The above code is faster then the below code on PowerPC/POWER for example, but slower on x86/amd64.<p><pre><code> int tmp = a; //or: register int tmp = a;
a = b;
b = tmp;</code></pre>
This is a pretty basic article, but might be useful for some.
One point I take issue with: a pointer in C is not simply a variable containing an address. It also knows (at compile time) how big the object pointed to is and so increments and decrements mean different things depending on the pointer type. In addition, void* is special because it does NOT know it's size.
Over using the pre-processor like this (creating "debug" type macros) always rubs me up the wrong way because of the hassle it is for me to read and ironically, to debug.<p>There are so many gotchas with writing good quality, safe macros and they're also not well handled by many tools. E.g. my IDE is pretty hopeless at following complex macros.<p>We've got better alternatives today. Unit testing is probably the first one everyone thinks of but i reckon switching to a graphical debugger (i used to only use CLI gdb) also reduced my need for these kind of hacks.<p>I feel like this article should be named "C's naughty bits", e.g. the array indexing in #7.<p>There are some good ones though, i like the idea of better separating code and data per #15.
Hi all! I never expected this to reach the front page! Thank you all!
This was a quick writeup of a talk I delivered in our college's Open Source Community (<a href="http://pesos.pes.edu" rel="nofollow">http://pesos.pes.edu</a>).
This was meant for beginners and average C programmers and summarized it through a blog post. I can understand few things do seem a bit different, but the post intends to mainly convey the idea than the exact implementation aspects!<p>Hope you enjoyed it! Thanks!
<p><pre><code> Feature/Trick #4 :
#ifndef FILE_H
#define FILE_H
...
#endif
</code></pre>
How is this "Cool C Programming"? What am I missing?
Not bad reading for a beginner/intermediate C programmer. However, if you are targeting such, try to emphasize more on possible pitfalls, things to avoid and best practices. What first comes to my mind:<p>1) Name variables in macro differently (e.g. _X instead of just X) and always use them in parentheses.<p>2) Always initialize pointers, especially in examples for beginners, as segmentation fault while stepping on uninitialized or dangling pointer is one of the most common errors I have seen.<p>3) Using -Wall compiler directive is also a good idea to see many possible problems you could miss otherwise.<p>4) Trick #15 is a really bad practice, it's way better to include header file that declares and defines array, something like Gimp or OpenSSL do when you choose to export output as a header file.<p>5) Just a suggestion: there is a very handy macro for debugging worth mentioning:<p><pre><code> #ifdef DEBUG
#define DBG(fmt, ...) \
printf("%s: " fmt, __func__, ## __VA_ARGS__)
#else
#define DBG(fmt, ...)
#endif</code></pre>
Might be obvious to some of you, but I use this to check what my macros expand out into to make sure the syntax is valid.<p><pre><code> #include <stdio.h>
#define atoa(x) #x
#define mdb(x) printf("%s\n", atoa(x))
#define swap(type, x, y) do {type temp = *(x); *(x) = *(y); *(y) = temp;} while(0)
int main(int argc, char *argv[])
{
int cat[2] = {33, 44};
printf("atoa(cat): %s\n", atoa(cat)); // "cat"
mdb(swap(int, cat, cat+1)); // expands the macro inside to text
swap(int, cat, cat+1); // the macro itself
printf("cat[0]: %d\n", cat[0]); // 44
return 0;
}</code></pre>
When I was in highschool we had this debugging macro:<p><pre><code> #define dbg(...) fprintf(stderr, __VA_ARGS__)
</code></pre>
So the dbg function is just a shortcut to "printf to stderr".
It also was easy to disable with #ifdef.
...erm... more 'C for newbs'.<p>Although, it does point out some interesting idioms of the language and I agree that scanf is bloody cool. IMO every language should have printf/scanf equivalents :o)
Anything involving the preprocessor ranks high in my favorite C trick (I once got a "clever abuse of the C preprocessor" notation after writing a C+ library for school written entirely using macros).<p>Actually, anything involving meta-programming is "cool". Knowing a language is "easy" once you get the logic, but manipulating the language to do the work for you is even more satisfying.
<p><pre><code> char* first_name; int age;
fscanf(fptr, "%s %d", first_name, &age);
printf("Name: %s\nAge: %d\n\n", first_name, age);
</code></pre>
Cool usage of uninitialized char* pointer bro.<p>(Sorry about the snarky tone, I just wanted to use that meme because it's appropriate.)
Cool tricks!<p>About the debugging macros: printf prints messages to stdout, not stderr. You want to use fprintf instead:<p><pre><code> fprintf(stderr ,"error message");
</code></pre>
This has the advantage of being unbuffered, and still printing to the console even if stdout has been directed to a file.
I was intrigued by the bit regarding array indexing, but I have yet to <i>break out vim and mod that C source</i>. How would this apply to multidimensional arrays?