I know there is a standard behind all C compiler implementations, so there should be no hidden features. Despite that, I am sure all C developers have hidden/secret tricks they use all the time.
using INT(3) to set break point at the code is my all time favorite
Well... I think that one of the strong points of C language is its portability and standardness, so whenever I find some "hidden trick" in the implementation I am currently using, I try not to use it because I try to keep my C code as standard and portable as possible.
Interlacing structures like Duff's Device:
strncpy(to, from, count)
char *to, *from;
int count;
{
int n = (count + 7) / 8;
switch (count % 8) {
case 0: do { *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while (--n > 0);
}
}
Early versions of gcc attempted to run a game whenever it encountered "#pragma" in the source code. See also here.
C has a standard but not all C compilers are fully compliant (I've not seen any fully compliant C99 compiler yet!).
That said, the tricks I prefer are those that are non-obvious and portable across platforms as they rely on the C semantic. They usually are about macros or bit arithmetic.
For example: swapping two unsigned integer without using a temporary variable:
...
a ^= b ; b ^= a; a ^=b;
...
or "extending C" to represent finite state machines like:
FSM {
STATE(x) {
...
NEXTSTATE(y);
}
STATE(y) {
...
if (x == 0)
NEXTSTATE(y);
else
NEXTSTATE(x);
}
}
that can be achieved with the following macros:
#define FSM
#define STATE(x) s_##x :
#define NEXTSTATE(x) goto s_##x
In general, though, I don't like the tricks that are clever but make the code unnecessarily complicated to read (as the swap example) and I love the ones that make the code clearer and directly conveying the intention (like the FSM example).
C compilers implement one of several standards. However, having a standard does not mean that all aspects of the language are defined. Duff's device, for example, is a favorite 'hidden' feature that has become so popular that modern compilers have special purpose recognition code to ensure that optimization techniques do not clobber the desired effect of this often used pattern.
In general hidden features or language tricks are discouraged as you are running on the razor edge of whichever C standard(s) your compiler uses. Many such tricks do not work from one compiler to another, and often these kinds of features will fail from one version of a compiler suite by a given manufacturer to another version.
Various tricks that have broken C code include:
- Relying on how the compiler lays out structs in memory.
- Assumptions on endianness of integers/floats.
- Assumptions on function ABIs.
- Assumptions on the direction that stack frames grow.
- Assumptions about order of execution within statements.
- Assumptions about order of execution of statements in function arguments.
- Assumptions on the bit size or precision of short, int, long, float and double types.
Other problems and issues that arise whenever programmers make assumptions about execution models that are all specified in most C standards as 'compiler dependent' behavior.
Strange vector indexing:
int v[100]; int index = 10;
/* v[index] it's the same thing as index[v] */
anonymous structures and arrays is my favourite one. (cf. http://www.run.montefiore.ulg.ac.be/~martin/resources/kung-f00.html)
setsockopt(yourSocket, SOL_SOCKET, SO_REUSEADDR, (int[]){1}, sizeof(int));
or
void myFunction(type* values) {
while(*values) x=*values++;
}
myFunction((type[]){val1,val2,val3,val4,0});
it can even be used to instanciate linked lists...
Function pointers. You can use a table of function pointers to implement, e.g., fast indirect-threaded code interpreters (FORTH) or byte-code dispatchers, or to simulate OO-like virtual methods.
Then there are hidden gems in the standard library, such as qsort(),bsearch(), strpbrk(), strcspn() [the latter two being useful for implementing a strtok() replacement].
A misfeature of C is that signed arithmetic overflow is undefined behavior (UB). So whenever you see an expression such as x+y, both being signed ints, it might potentially overflow and cause UB.
I never used bit fields but they sound cool for ultra-low-level stuff.
struct cat {
unsigned int legs:3; // 3 bits for legs (0-4 fit in 3 bits)
unsigned int lives:4; // 4 bits for lives (0-9 fit in 4 bits)
// ...
};
cat make_cat()
{
cat kitty;
kitty.legs = 4;
kitty.lives = 9;
return kitty;
}
This means that sizeof(cat)
can be as small as sizeof(char)
.
Multi-character constants:
int x = 'ABCD';
This sets x to 0x41424344 (or 0x44434241 depending on architecture).
EDIT: This technique is not portable, especially if you serialize the int. However, it can be extremely useful to create self-documenting enums. e.g.
enum state {
stopped = 'STOP',
running = 'RUN!',
waiting = 'WAIT',
};
This makes it much simpler if you're looking at a raw memory dump and need to determine the value of an enum without having to look it up.
I got shown this in a bit of code once, and asked what it did:
hexDigit = "0123456789abcdef"[someNybble];
Another favorite is:
unsigned char bar[100];
unsigned char *foo = bar;
unsigned char blah = 42[foo];
Not really a hidden feature, but it looked to me like voodoo, the first time I saw something like this:
void callback(const char *msg, void *data)
{
// do something with msg, e.g.
printf("%s\n", msg);
return;
data = NULL;
}
The reason for this construction is, that if you compile this with -Wextra and without the "data = NULL;"-line, gcc will spit out a warning about unused parameters. But with this useless line you don't get a warning.
EDIT: I know there are other (better) ways to prevent those warnings. It just looked strange to me, the first time I saw this.
More of a trick of the GCC compiler, but you can give branch indication hints to the compiler (common in the Linux kernel)
#define likely(x) __builtin_expect((x),1)
#define unlikely(x) __builtin_expect((x),0)
see: http://kerneltrap.org/node/4705
What I like about this is that it also adds some expressiveness to some functions.
void foo(int arg)
{
if (unlikely(arg == 0)) {
do_this();
return;
}
do_that();
...
}
I'm very fond of designated initializers, added in C99 (and supported in gcc for a long time):
#define FOO 16
#define BAR 3
myStructType_t myStuff[] = {
[FOO] = { foo1, foo2, foo3 },
[BAR] = { bar1, bar2, bar3 },
...
The array initialization is no longer position dependent. If you change the values of FOO or BAR, the array initialization will automatically correspond to their new value.
Variable size automatic variables are also useful in some cases. These were added i nC99 and have been supported in gcc for a long time.
void foo(uint32_t extraPadding) {
uint8_t commBuffer[sizeof(myProtocol_t) + extraPadding];
You end up with a buffer on the stack with room for the fixed-size protocol header plus variable size data. You can get the same effect with alloca(), but this syntax is more compact.
You have to make sure extraPadding is a reasonable value before calling this routine, or you end up blowing the stack. You'd have to sanity check the arguments before calling malloc or any other memory allocation technique, so this isn't really unusual.
int8_t
int16_t
int32_t
uint8_t
uint16_t
uint32_t
These are an optional item in the standard, but it must be a hidden feature, because people are constantly redefining them. One code base I've worked on (and still do, for now) has multiple redefinitions, all with different identifiers. Most of the time it's with preprocessor macros:
#define INT16 short
#define INT32 long
And so on. It makes me want to pull my hair out. Just use the freaking standard integer typedefs!
The comma operator isn't widely used. It can certainly be abused, but it can also be very useful. This use is the most common one:
for (int i=0; i<10; i++, doSomethingElse())
{
/* whatever */
}
But you can use this operator anywhere. Observe:
int j = (printf("Assigning variable j\n"), getValueFromSomewhere());
Each statement is evaluated, but the value of the expression will be that of the last statement evaluated.
Conversion of types by using unusual typecasts. Though not hidden feature, its quite tricky.
Example:
If you needed to know how compiler stores float, just try this:
uint32_t Int;
float flt = 10.5; // say
Int = *(uint32_t *)&flt;
printf ("Float 10.5 is stored internally as %8X\n", Int);
or
float flt = 10.5; // say
printf ("Float 10.5 is stored internally as %8X\n", *(uint32_t *)&flt);
Note the clever use of typecasts. Converting address of variable (here &flt) to desired type (here (uint32_t * )) and extracting its content (applying '*').
This works other side of expression as well:
*(float *)&Int = flt;
This could also be accomplished using union:
typedef union
{
uint32_t Int;
float flt;
} FloatInt_type;
I liked the variable sized structures you could make:
typedef struct {
unsigned int size;
char buffer[1];
} tSizedBuffer;
tSizedBuffer *buff = (tSizedBuffer*)(malloc(sizeof(tSizedBuffer) + 99));
// can now refer to buff->buffer[0..99].
Also the offsetof macro which is now in ANSI C but was a piece of wizardry the first time I saw it. It basically uses the address-of operator (&) for a null pointer recast as a structure variable.
My favorite "hidden" feature of C, is the usage of %n in printf to write back to the stack. Normally printf pops the parameter values from the stack based on the format string, but %n can write them back.
Check out section 3.4.2 here. Can lead to a lot of nasty vulnerabilities.
gcc has a number of extensions to the C language that I enjoy, which can be found here. Some of my favorites are function attributes. One extremely useful example is the format attribute. This can be used if you define a custom function that takes a printf format string. If you enable this function attribute, gcc will do checks on your arguments to ensure that your format string and arguments match up and will generate warnings or errors as appropriate.
int my_printf (void *my_object, const char *my_format, ...)
__attribute__ ((format (printf, 2, 3)));
register variables
I used to declare some variables with the register
keyword to help speed things up. This would give a hint to the C compiler to use a CPU register as local storage. This is most likely no longer necessary as modern day C compilers do this automatically.
initializing structure to zero
struct mystruct a = {0};
this will zero all stucture elements.
Struct assignment is cool. Many people don't seem to realize that structs are values too, and can be assigned around, there is no need to use memcpy()
, when a simple assignment does the trick.
For example, consider some imaginary 2D graphics library, it might define a type to represent an (integer) screen coordinate:
typedef struct {
int x;
int y;
} Point;
Now, you do things that might look "wrong", like write a function that creates a point initialized from function arguments, and returns it, like so:
Point point_new(int x, int y)
{
Point p;
p.x = x;
p.y = y;
return p;
}
This is safe, as long (of course) as the return value is copied by value using struct assignment:
Point origin;
origin = point_new(0, 0);
In this way you can write quite clean and object-oriented-ish code, all in plain standard C.
Well, I've never used it, and I'm not sure whether I'd ever recommend it to anyone, but I feel this question would be incomplete without a mention of Simon Tatham's co-routine trick.
Compile-time assertions, as already discussed here.
//--- size of static_assertion array is negative if condition is not met
#define STATIC_ASSERT(condition) \
typedef struct { \
char static_assertion[condition ? 1 : -1]; \
} static_assertion_t
//--- ensure structure fits in
STATIC_ASSERT(sizeof(mystruct_t) <= 4096);
C99-style variable argument macros, aka
#define ERR(name, fmt, ...) fprintf(stderr, "ERROR " #name ": " fmt "\n", \
__VAR_ARGS__)
which would be used like
ERR(errCantOpen, "File %s cannot be opened", filename);
Here I also use the stringize operator and string constant concatentation, other features I really like.
Excerpt:
In this page, you will find a list of interesting C programming questions/puzzles, These programs listed are the ones which I have received as e-mail forwards from my friends, a few I read in some books, a few from the internet, and a few from my coding experiences in C.
When initializing arrays or enums, you can put a comma after the last item in the initializer list. e.g:
int x[] = { 1, 2, 3, };
enum foo { bar, baz, boom, };
This was done so that if you're generating code automatically you don't need to worry about eliminating the last comma.
Gcc (c) has some fun features you can enable, such as nested function declarations, and the a?:b form of the ?: operator, which returns a if a is not false.
-Alex
Say you have a struct with members of the same type:
struct Point {
float x;
float y;
float z;
};
You can cast instances of it to a float pointer and use array indices:
Point a;
int sum = 0, i = 0;
for( ; i < 3; i++)
sum += ((float*)a)[i];
Pretty elementary, but useful when writing concise code.
Variable-sized structs, seen in common resolver libs among other places.
struct foo { int a; int b; char b[1]; // using [0] is no longer correct // must come at end }; char *str = "abcdef"; int len = strlen(str); struct foo *bar = malloc(sizeof(foo) + len); strcpy(bar.b, str); // try and stop me!
Wrap malloc and realloc like this:
#ifdef _DEBUG
#define mmalloc(bytes) malloc(bytes);printf("malloc: %d\t<%s@%d>\n", bytes, __FILE__, __LINE__);
#define mrealloc(pointer, bytes) realloc(pointer, bytes);printf("realloc: %d\t<%s@%d>\n", bytes, __FILE__, __LINE__);
#else //_DEBUG
#define mmalloc(bytes) malloc(bytes)
#define mrealloc(pointer, bytes) realloc(pointer, bytes)
In fact, here is my full arsenol (The BailIfNot is for OO c):
#ifdef _DEBUG
#define mmalloc(bytes) malloc(bytes);printf("malloc: %d\t<%s@%d>\n", bytes, __FILE__, __LINE__);
#define mrealloc(pointer, bytes) realloc(pointer, bytes);printf("realloc: %d\t<%s@%d>\n", bytes, __FILE__, __LINE__);
#define BAILIFNOT(Node, Check) if(Node->type != Check) return 0;
#define NULLCHECK(var) if(var == NULL) setError(__FILE__, __LINE__, "Null exception", " var ", FATAL);
#define ASSERT(n) if( ! ( n ) ) { printf("<ASSERT FAILURE@%s:%d>", __FILE__, __LINE__); fflush(0); __asm("int $0x3"); }
#define TRACE(n) printf("trace: %s <%s@%d>\n", n, __FILE__, __LINE__);fflush(0);
#else //_DEBUG
#define mmalloc(bytes) malloc(bytes)
#define mrealloc(pointer, bytes) realloc(pointer, bytes)
#define BAILIFNOT(Node, Check) {}
#define NULLCHECK(var) {}
#define ASSERT(n) {}
#define TRACE(n) {}
#endif //_DEBUG
Here is some example output:
malloc: 12 <hash.c@298>
trace: nodeCreate <hash.c@302>
malloc: 5 <hash.c@308>
malloc: 16 <hash.c@316>
malloc: 256 <hash.c@320>
trace: dataLoadHead <hash.c@441>
malloc: 270 <hash.c@463>
malloc: 262144 <hash.c@467>
trace: dataLoadRecursive <hash.c@404>
I just read this article. It has some C and several other languages "hidden features".
Object oriented C macros: You need a constructor (init), a destructor (dispose), an equal (equal), a copier (copy), and some prototype for instantiation (prototype).
With the declaration, you need to declare a constant prototype to copy and derive from. Then you can do C_OO_NEW
. I can post more examples if needed. LibPurple is a large object oriented C code base with a callback system (if you want to see one in use)
#define C_copy(to, from) to->copy(to, from)
#define true 1
#define false 0
#define C_OO_PROTOTYPE(type)\
void type##_init (struct type##_struct *my);\
void type##_dispose (struct type##_struct *my);\
char type##_equal (struct type##_struct *my, struct type##_struct *yours); \
struct type##_struct * type##_copy (struct type##_struct *my, struct type##_struct *from); \
const type type##__prototype = {type##_init, type##_dispose, type##_equal, type##_copy
#define C_OO_OVERHEAD(type)\
void (*init) (struct type##_struct *my);\
void (*dispose) (struct type##_struct *my);\
char (*equal) (struct type##_struct *my, struct type##_struct *yours); \
struct type##_struct *(*copy) (struct type##_struct *my, struct type##_struct *from);
#define C_OO_IN(ret, type, function, ...) ret (* function ) (struct type##_struct *my, __VA_ARGS__);
#define C_OO_OUT(ret, type, function, ...) ret type##_##function (struct type##_struct *my, __VA_ARGS__);
#define C_OO_PNEW(type, instance)\
instance = ( type *) malloc(sizeof( type ));\
memcpy(instance, & type##__prototype, sizeof( type ));
#define C_OO_NEW(type, instance)\
type instance;\
memcpy(&instance, & type ## __prototype, sizeof(type));
#define C_OO_DELETE(instance)\
instance->dispose(instance);\
free(instance);
#define C_OO_INIT(type) void type##_init (struct type##_struct *my){return;}
#define C_OO_DISPOSE(type) void type##_dispose (struct type##_struct *my){return;}
#define C_OO_EQUAL(type) char type##_equal (struct type##_struct *my, struct type##_struct *yours){return 0;}
#define C_OO_COPY(type) struct type##_struct * type##_copy (struct type##_struct *my, struct type##_struct *from){return 0;}
I like the typeof() operator. It works like sizeof() in that it is resolved at compile time. Instead of returning the number of bytes, it returns the type. This is useful when you need to declare a variable to be the same type as some other variable, whatever type it may be.
typeof(foo) copy_of_foo; //declare bar to be a variable of the same type as foo
copy_of_foo = foo; //now copy_of_foo has a backup of foo, for any type
This might be just a gcc extension, I'm not sure.
the (hidden) feature that "shocked" me when I first saw is about printf. this feature allows you to use variables for formatting format specifiers themselves. look for the code, you will see better:
#include <stdio.h>
int main() {
int a = 3;
float b = 6.412355;
printf("%.*f\n",a,b);
return 0;
}
the * character achieves this effect.
For clearing the input buffer you can't use fflush(stdin)
. The correct way is as follows: scanf("%*[^\n]%*c")
This will discard everything from the input buffer.
I only discovered this after 15+ years of C programming:
struct SomeStruct
{
unsigned a : 5;
unsigned b : 1;
unsigned c : 7;
};
Bitfields! The number after the colon is the number of bits the member requires, with members packed into the specified type, so the above would look like the following if unsigned is 16 bits:
xxxc cccc ccba aaaa
Skizz
Compile-time assumption-checking using enums: Stupid example, but can be really useful for libraries with compile-time configurable constants.
#define D 1
#define DD 2
enum CompileTimeCheck
{
MAKE_SURE_DD_IS_TWICE_D = 1/(2*(D) == (DD)),
MAKE_SURE_DD_IS_POW2 = 1/((((DD) - 1) & (DD)) == 0)
};
intptr_t for declaring variables of type pointer. C99 specific and declared in stdint.h
Lambda's (e.g. anonymous functions) in GCC:
#define lambda(return_type, function_body) \
({ return_type fn function_body fn })
This can be used as:
lambda (int, (int x, int y) { return x > y; })(1, 2)
Which is expanded into:
({ int fn (int x, int y) { return x > y } fn; })(1, 2)
Constant string concatenation
I was quite surprised not seeing it allready in the answers, as all compilers I know of support it, but many programmers seems to ignore it. Sometimes it's really handy and not only when writing macros.
Use case I have in my current code:
I have a #define PATH "/some/path/"
in a configuration file (really it is setted by the makefile). Now I want to build the full path including filenames to open ressources. It just goes to:
fd = open(PATH "/file", flags);
Instead of the horrible, but very common:
char buffer[256];
snprintf(buffer, 256, "%s/file", PATH);
fd = open(buffer, flags);
Notice that the common horrible solution is:
- three times as long
- much less easy to read
- much slower
- less powerfull at it set to an arbitrary buffer size limit (but you would have to use even longer code to avoid that without constant strings contatenation).
- use more stack space
I like __LINE__
and __FILE__
. See here: http://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html
When using sscanf you can use %n to find out where you should continue to read:
sscanf ( string, "%d%n", &number, &length );
string += length;