[ACCEPTED]-Hidden features of C-hidden-features

Accepted answer
Score: 115

More of a trick of the GCC compiler, but 4 you can give branch indication hints to 3 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 2 I like about this is that it also adds some 1 expressiveness to some functions.

void foo(int arg)
{
     if (unlikely(arg == 0)) {
           do_this();
           return;
     }
     do_that();
     ...
}
Score: 77
int8_t
int16_t
int32_t
uint8_t
uint16_t
uint32_t

These are an optional item in the standard, but 7 it must be a hidden feature, because people 6 are constantly redefining them. One code 5 base I've worked on (and still do, for now) has 4 multiple redefinitions, all with different 3 identifiers. Most of the time it's with 2 preprocessor macros:

#define INT16 short
#define INT32  long

And so on. It makes 1 me want to pull my hair out. Just use the freaking standard integer typedefs!

Score: 72

The comma operator isn't widely used. It 6 can certainly be abused, but it can also 5 be very useful. This use is the most common 4 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 3 statement is evaluated, but the value of 2 the expression will be that of the last 1 statement evaluated.

Score: 63

initializing structure to zero

struct mystruct a = {0};

this will zero all stucture elements.

0

Score: 62

Function pointers. You can use a table 12 of function pointers to implement, e.g., fast 11 indirect-threaded code interpreters (FORTH) or 10 byte-code dispatchers, or to simulate OO-like 9 virtual methods.

Then there are hidden gems 8 in the standard library, such as qsort(),bsearch(), strpbrk(), strcspn() [the 7 latter two being useful for implementing 6 a strtok() replacement].

A misfeature of 5 C is that signed arithmetic overflow is 4 undefined behavior (UB). So whenever you 3 see an expression such as x+y, both being 2 signed ints, it might potentially overflow 1 and cause UB.

Score: 52

Multi-character constants:

int x = 'ABCD';

This sets x to 8 0x41424344 (or 0x44434241, depending on architecture).

EDIT: This 7 technique is not portable, especially if 6 you serialize the int. However, it can be 5 extremely useful to create self-documenting 4 enums. e.g.

enum state {
    stopped = 'STOP',
    running = 'RUN!',
    waiting = 'WAIT',
};

This makes it much simpler if 3 you're looking at a raw memory dump and 2 need to determine the value of an enum without 1 having to look it up.

Score: 44

I never used bit fields but they sound cool for ultra-low-level 3 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 2 sizeof(char).


Incorporated comments by Aaron and leppie, thanks 1 guys.

Score: 37

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);
    }
}

0

Score: 37

C has a standard but not all C compilers 16 are fully compliant (I've not seen any fully 15 compliant C99 compiler yet!).

That said, the 14 tricks I prefer are those that are non-obvious 13 and portable across platforms as they rely 12 on the C semantic. They usually are about 11 macros or bit arithmetic.

For example: swapping 10 two unsigned integer without using a temporary 9 variable:

...
a ^= b ; b ^= a; a ^=b;
...

or "extending C" to represent finite 8 state machines like:

FSM {
  STATE(x) {
    ...
    NEXTSTATE(y);
  }

  STATE(y) {
    ...
    if (x == 0) 
      NEXTSTATE(y);
    else 
      NEXTSTATE(x);
  }
}

that can be achieved 7 with the following macros:

#define FSM
#define STATE(x)      s_##x :
#define NEXTSTATE(x)  goto s_##x

In general, though, I 6 don't like the tricks that are clever but 5 make the code unnecessarily complicated 4 to read (as the swap example) and I love 3 the ones that make the code clearer and 2 directly conveying the intention (like the 1 FSM example).

Score: 33

I'm very fond of designated initializers, added 6 in C99 (and supported in gcc for a long 5 time):

#define FOO 16
#define BAR 3

myStructType_t myStuff[] = {
    [FOO] = { foo1, foo2, foo3 },
    [BAR] = { bar1, bar2, bar3 },
    ...

The array initialization is no longer 4 position dependent. If you change the values 3 of FOO or BAR, the array initialization 2 will automatically correspond to their new 1 value.

Score: 28

C99 has some awesome any-order structure 1 initialization.

struct foo{
  int x;
  int y;
  char* name;
};

void main(){
  struct foo f = { .y = 23, .name = "awesome", .x = -38 };
}

Score: 27

anonymous structures and arrays is my favourite 2 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 1 linked lists...

Score: 24

Well... I think that one of the strong points 5 of C language is its portability and standardness, so 4 whenever I find some "hidden trick" in the 3 implementation I am currently using, I try 2 not to use it because I try to keep my C 1 code as standard and portable as possible.

Score: 24

the (hidden) feature that "shocked" me when 5 I first saw is about printf. this feature 4 allows you to use variables for formatting 3 format specifiers themselves. look for the 2 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 1 achieves this effect.

Score: 24

gcc has a number of extensions to the C 10 language that I enjoy, which can be found 9 here. Some of my favorites are function attributes. One extremely 8 useful example is the format attribute. This 7 can be used if you define a custom function 6 that takes a printf format string. If you 5 enable this function attribute, gcc will 4 do checks on your arguments to ensure that 3 your format string and arguments match up 2 and will generate warnings or errors as 1 appropriate.

int my_printf (void *my_object, const char *my_format, ...)
            __attribute__ ((format (printf, 2, 3)));
Score: 19

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);

0

Score: 16

Constant string concatenation

I was quite surprised not seeing it allready 11 in the answers, as all compilers I know 10 of support it, but many programmers seems 9 to ignore it. Sometimes it's really handy 8 and not only when writing macros.

Use case 7 I have in my current code: I have a #define PATH "/some/path/" in 6 a configuration file (really it is setted 5 by the makefile). Now I want to build the 4 full path including filenames to open ressources. It 3 just goes to:

fd = open(PATH "/file", flags);

Instead of the horrible, but 2 very common:

char buffer[256];
snprintf(buffer, 256, "%s/file", PATH);
fd = open(buffer, flags);

Notice that the common horrible 1 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
Score: 15

Well, I've never used it, and I'm not sure 3 whether I'd ever recommend it to anyone, but 2 I feel this question would be incomplete 1 without a mention of Simon Tatham's co-routine trick.

Score: 12

Struct assignment is cool. Many people don't 14 seem to realize that structs are values 13 too, and can be assigned around, there is 12 no need to use memcpy(), when a simple assignment 11 does the trick.

For example, consider some 10 imaginary 2D graphics library, it might 9 define a type to represent an (integer) screen 8 coordinate:

typedef struct {
   int x;
   int y;
} Point;

Now, you do things that might 7 look "wrong", like write a function that 6 creates a point initialized from function 5 arguments, and returns it, like so:

Point point_new(int x, int y)
{
  Point p;
  p.x = x;
  p.y = y;
  return p;
}

This 4 is safe, as long (of course) as the return 3 value is copied by value using struct assignment:

Point origin;
origin = point_new(0, 0);

In 2 this way you can write quite clean and object-oriented-ish 1 code, all in plain standard C.

Score: 12

When initializing arrays or enums, you can 5 put a comma after the last item in the initializer 4 list. e.g:

int x[] = { 1, 2, 3, };

enum foo { bar, baz, boom, };

This was done so that if you're 3 generating code automatically you don't 2 need to worry about eliminating the last 1 comma.

Score: 10

Strange vector indexing:

int v[100]; int index = 10; 
/* v[index] it's the same thing as index[v] */

0

Score: 9

When using sscanf you can use %n to find 4 out where you should continue to read:

sscanf ( string, "%d%n", &number, &length );
string += length;

Apparently, you 3 can't add another answer, so I'll include 2 a second one here, you can use "&&" and 1 "||" as conditionals:

#include <stdio.h>
#include <stdlib.h>

int main()
{
   1 || puts("Hello\n");
   0 || puts("Hi\n");
   1 && puts("ROFL\n");
   0 && puts("LOL\n");

   exit( 0 );
}

This code will output:

Hi
ROFL
Score: 9

C compilers implement one of several standards. However, having 20 a standard does not mean that all aspects 19 of the language are defined. Duff's device, for example, is 18 a favorite 'hidden' feature that has become 17 so popular that modern compilers have special 16 purpose recognition code to ensure that 15 optimization techniques do not clobber the 14 desired effect of this often used pattern.

In 13 general hidden features or language tricks 12 are discouraged as you are running on the 11 razor edge of whichever C standard(s) your 10 compiler uses. Many such tricks do not 9 work from one compiler to another, and often 8 these kinds of features will fail from one 7 version of a compiler suite by a given manufacturer 6 to another version.

Various tricks that have 5 broken C code include:

  1. Relying on how the compiler lays out structs in memory.
  2. Assumptions on endianness of integers/floats.
  3. Assumptions on function ABIs.
  4. Assumptions on the direction that stack frames grow.
  5. Assumptions about order of execution within statements.
  6. Assumptions about order of execution of statements in function arguments.
  7. Assumptions on the bit size or precision of short, int, long, float and double types.

Other problems and 4 issues that arise whenever programmers make 3 assumptions about execution models that 2 are all specified in most C standards as 1 'compiler dependent' behavior.

Score: 8

using INT(3) to set break point at the code 1 is my all time favorite

Score: 8

Gcc (c) has some fun features you can enable, such 3 as nested function declarations, and the 2 a?:b form of the ?: operator, which returns 1 a if a is not false.

Score: 8

My favorite "hidden" feature of 6 C, is the usage of %n in printf to write 5 back to the stack. Normally printf pops 4 the parameter values from the stack based 3 on the format string, but %n can write them 2 back.

Check out section 3.4.2 here. Can lead 1 to a lot of nasty vulnerabilities.

Score: 8

Compile-time assumption-checking using enums: Stupid 2 example, but can be really useful for libraries 1 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)
};
Score: 8

I discoverd recently 0 bitfields.

struct {
  int    a:3;
  int    b:2;
  int     :0;
  int    c:4;
  int    d:3;
};

which will 4 give a layout of

000aaabb 0ccccddd

instead of without the :0;

0000aaab bccccddd

The 3 0 width field tells that the following bitfields 2 should be set on the next atomic entity 1 (char)

Score: 7

C99-style variable argument macros, aka

#define ERR(name, fmt, ...)   fprintf(stderr, "ERROR " #name ": " fmt "\n", \
                                  __VAR_ARGS__)

which 3 would be used like

ERR(errCantOpen, "File %s cannot be opened", filename);

Here I also use the stringize 2 operator and string constant concatentation, other 1 features I really like.

Score: 6

Variable size automatic variables are also 13 useful in some cases. These were added i 12 nC99 and have been supported in gcc for 11 a long time.

void foo(uint32_t extraPadding) {
    uint8_t commBuffer[sizeof(myProtocol_t) + extraPadding];

You end up with a buffer on 10 the stack with room for the fixed-size protocol 9 header plus variable size data. You can 8 get the same effect with alloca(), but this 7 syntax is more compact.

You have to make 6 sure extraPadding is a reasonable value 5 before calling this routine, or you end 4 up blowing the stack. You'd have to sanity 3 check the arguments before calling malloc 2 or any other memory allocation technique, so 1 this isn't really unusual.

Score: 5

I liked the variable sized structures you 5 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 4 is now in ANSI C but was a piece of wizardry 3 the first time I saw it. It basically uses 2 the address-of operator (&) for a null 1 pointer recast as a structure variable.

Score: 5

Lambda's (e.g. anonymous functions) in GCC:

#define lambda(return_type, function_body) \
    ({ return_type fn function_body fn })

This 1 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)
Score: 5

I like __LINE__ and __FILE__. See here: http://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html

0

Score: 4

For clearing the input buffer you can't 2 use fflush(stdin). The correct way is as follows: scanf("%*[^\n]%*c") This 1 will discard everything from the input buffer.

Score: 3

Early versions of gcc attempted to run a 2 game whenever it encountered "#pragma" in 1 the source code. See also here.

Score: 3

I got shown this in a bit of code once, and 1 asked what it did:


hexDigit = "0123456789abcdef"[someNybble];

Another favorite is:


unsigned char bar[100];
unsigned char *foo = bar;
unsigned char blah = 42[foo];
Score: 3

I only discovered this after 15+ years of 5 C programming:

struct SomeStruct
{
   unsigned a : 5;
   unsigned b : 1;
   unsigned c : 7;
};

Bitfields! The number after 4 the colon is the number of bits the member 3 requires, with members packed into the specified 2 type, so the above would look like the following 1 if unsigned is 16 bits:

xxxc cccc ccba aaaa

Skizz

Score: 3

Conversion of types by using unusual typecasts. Though 8 not hidden feature, its quite tricky.

Example:

If 7 you needed to know how compiler stores float, just 6 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 5 address of variable (here &flt) to desired 4 type (here (uint32_t * )) and extracting 3 its content (applying '*').

This works other 2 side of expression as well:

*(float *)&Int = flt;

This could also 1 be accomplished using union:

typedef union
{
  uint32_t Int;
  float    flt;

} FloatInt_type;
Score: 2

Not really a hidden feature, but it looked 9 to me like voodoo, the first time I saw 8 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 7 construction is, that if you compile this 6 with -Wextra and without the "data = NULL;"-line, gcc 5 will spit out a warning about unused parameters. But 4 with this useless line you don't get a warning.

EDIT: I 3 know there are other (better) ways to prevent 2 those warnings. It just looked strange to 1 me, the first time I saw this.

Score: 2

intptr_t for declaring variables of type 1 pointer. C99 specific and declared in stdint.h

Score: 2

Steve Webb has pointed out the __LINE__ and __FILE__ macros. It reminds 23 me of how in my previous job I had hacked 22 them to have in-memory logging.

I was working 21 on a device where there was no port available 20 to pass logging information from device 19 to the PC being used for debugging. One 18 could use breakpoints to halt and know the 17 state of the program using debugger but 16 there was no information on system trace.

Since 15 all calls to debug logs were effectively 14 a single global macro, we changed that macro 13 to dump file name and line number on to 12 a global array. This array contained series 11 of file names and line numbers showing which 10 debug calls were invoked, giving a fair 9 idea of execution trace (not the actual 8 log message though). One could pause the 7 execution by debugger, dump these bytes 6 onto a local file and then map this information 5 to the code base using scripts. This was 4 made possible because we had strict coding 3 guidelines, so we could make had to make 2 changes to the logging mechanism in one 1 file.

Score: 2

When comparing a variable to a literal, it 7 is better to put the literal to the left of 6 the == operator, to make the sure the compiler 5 gives an error when you mistakenly use the 4 assignment operator instead.

if (0 == count) {
    ...
}

Might look weird 3 at first glance, but it could save some 2 headache (like if you happened to type if (count = 0) by 1 mistake).

Score: 1

Say you have a struct with members of the 4 same type:

struct Point {
    float x;
    float y;
    float z;
};

You can cast instances of it to 3 a float pointer and use array indices:

Point a;
int sum = 0, i = 0;
for( ; i < 3; i++)
    sum += ((float*)a)[i];

Pretty 2 elementary, but useful when writing concise 1 code.

Score: 1

register variables

I used to declare some variables with the 5 register keyword to help speed things up. This 4 would give a hint to the C compiler to use 3 a CPU register as local storage. This is 2 most likely no longer necessary as modern 1 day C compilers do this automatically.

Score: 1

Here's three nice ones in gcc:

__FILE__ 
__FUNCTION__
__LINE__

0

Score: 1

Excerpt:

In this page, you will find a list of interesting 6 C programming questions/puzzles, These 5 programs listed are the ones which I have received 4 as e-mail forwards from my friends, a 3 few I read in some books, a few from the 2 internet, and a few from my coding experiences 1 in C.

http://www.gowrikumar.com/c/index.html

Score: 1

The size of function pointers is not standard. At 23 least not in the K&R book. Even though 22 it talks about size of other types of pointers 21 but (I think) sizeof of a function pointer is 20 undefined behavior.

Also sizeof is a compile time 19 operator, I see a lot of people asking if 18 sizeof is a function or an operator in online 17 forums.

One error that I have seen is as 16 follows (a simplified example):

int j;
int i;
j = sizeof(i++)

the increment 15 on i would not be executed as sizeof is evaluated 14 at compile time. The programmer intended 13 to hack both operations, increment on i and 12 calculation of sizeof in one statement.

Operator 11 precedence in C governs order of association 10 not order of evaluation. For example if 9 you have three functions f,g,h each returning 8 an int, and their is an expression like:

f() + g() * h()

C standard 7 doesn't give rule about order of evaluation 6 of these functions. Result of g and h would 5 be multiplied before adding result of f. This 4 can lead to error if the functions share 3 state and computation depends on order of 2 evaluation of these functions. This can 1 lead to portability issues.

Score: 0

Variable-sized structs, seen in common resolver 1 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!
Score: 0

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 2 is my full arsenol (The BailIfNot is for 1 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>
Score: 0

I just read this article. It has some C and several 1 other languages "hidden features".

Score: 0

Object oriented C macros: You need a constructor 9 (init), a destructor (dispose), an equal 8 (equal), a copier (copy), and some prototype 7 for instantiation (prototype).

With the declaration, you 6 need to declare a constant prototype to 5 copy and derive from. Then you can do C_OO_NEW. I 4 can post more examples if needed. LibPurple 3 is a large object oriented C code base with 2 a callback system (if you want to see one 1 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;}
Score: 0

I like the typeof() operator. It works 7 like sizeof() in that it is resolved at 6 compile time. Instead of returning the 5 number of bytes, it returns the type. This 4 is useful when you need to declare a variable 3 to be the same type as some other variable, whatever 2 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 1 extension, I'm not sure.

Score: 0

The often forgotten %n specifier in printf format 6 string can be quite practical sometimes. %n 5 returns the current position of the imaginary 4 cursor used when printf formats its output.

int pos1, pos2;
 char *string_of_unknown_length = "we don't care about the length of this";

  printf("Write text of unknown %n(%s)%n text\n", &pos1, string_of_unknown_length, &pos2);
  printf("%*s\\%*s/\n", pos1, " ", pos2-pos1-2, " ");
  printf("%*s", pos1+1, " ");
  for(int i=pos1+1; i<pos2-1; i++)
    putc('-', stdout);
  putc('\n', stdout);

will 3 have following output

Write text of unknown (we don't care about the length of this) text
                      \                                      /
                       --------------------------------------

Granted a little bit 2 contrived but can have some uses when making 1 pretty reports.

Score: 0

How about using while(0) inside a switch 2 so you can use continue statements like 1 break :-)

void sw(int s)
{
    switch (s) while (0) {
    case 0:
        printf("zero\n");
        continue;
    case 1:
        printf("one\n");
        continue;
    default:
        printf("something else\n");
        continue;
    }
}
Score: 0

Use NaN for chained calculations / error 11 return :

//#include <stdint.h>
static 10 uint64_t iNaN = 0xFFF8000000000000;
const 9 double NaN = *(double *)&iNaN; // quiet 8 NaN

An inner function can return NaN as an 7 error flag : it can safely be used in any 6 calculation, and the result will always 5 be NaN.

note : testing for NaN is tricksy, since 4 NaN != NaN... use isnan(x), or roll your 3 own.
x!=x is mathematically correct if x 2 is NaN, but tends to get optimised out by 1 some compilers

More Related questions