Alex Rivera | Logout

Hidden features of C

Asked 2008-09-25T09:02:06.717
141

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.

Edit
Report

4 Answers

8

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

answered 2008-09-25T09:06:39.590
5

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.

answered 2008-09-26T06:56:18.197
2

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

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

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

answered 2011-01-07T04:38:18.783
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 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>
answered 2009-06-22T06:28:39.797

Your Answer