获取数组长度

///  Obtain the number of elements in the given C array
#define GET_ARRAY_LEN( arrayName ) (sizeof( arrayName ) / sizeof(( arrayName)[ 0 ] ))

使用例子:

#include <stdio.h>

///  Obtain the number of elements in the given C array
#define GET_ARRAY_LEN( arrayName ) (sizeof( arrayName ) / sizeof(( arrayName)[ 0 ] ))

int main()
{
    int iarray[20] = {0};
    printf("iarray len = %d\n",GET_ARRAY_LEN(iarray));

    char carray[40] = {0};
    printf("carray len = %d\n",GET_ARRAY_LEN(carray));
    return 0;
}

比较数字大小

/// Return min of two numbers. Commonly used but never defined as part of standard headers
#ifndef MIN
#define MIN( n1, n2 )   ((n1) > (n2) ? (n2) : (n1))
#endif

/// Return max of two numbers. Commonly used but never defined as part of standard headers
#ifndef MAX
#define MAX( n1, n2 )   ((n1) > (n2) ? (n1) : (n2))
#endif

使用例子:

#include <stdio.h>

/// Return min of two numbers. Commonly used but never defined as part of standard headers
#ifndef MIN
#define MIN( n1, n2 )   ((n1) > (n2) ? (n2) : (n1))
#endif

/// Return max of two numbers. Commonly used but never defined as part of standard headers
#ifndef MAX
#define MAX( n1, n2 )   ((n1) > (n2) ? (n1) : (n2))
#endif

int main()
{
    printf("MIN(3,5) = %d\n",MIN(3,5));
    printf("MAX(3,5) = %d\n",MAX(3,5));
    printf("MIN(3,MAX(3,5)) = %d\n",MIN(3,MAX(3,5)));
    printf("MIN(MIN(3,5),5) = %d\n",MIN(MIN(3,5),5));

    return 0;
}

判断奇偶数和数字是否在区间内

/// Determine whether the given signed or unsigned integer is odd.
#define IS_ODD( num )   ((num) & 1)

/// Determine whether the given signed or unsigned integer is even.
#define IS_EVEN( num )  (!IS_ODD( (num) ))

/**
Determine whether the given number is between the other two numbers
(both inclusive).
*/
#define IS_BETWEEN( numToTest, numLow, numHigh ) \
        ((unsigned char)((numToTest) >= (numLow) && (numToTest) <= (numHigh)))

结构体成员偏移量

C语言宏offset用法

判断大端小端

/**
Determines whether the memory architecture of current processor is LittleEndian.
*/

#define IS_LITTLE_ENDIAN()  (((*(short *)"21") & 0xFF) == '2')

/**
Determines whether the memory architecture of current processor is BigEndian.
*/
#define IS_BIG_ENDIAN()     (((*(short *)"21") & 0xFF) == '1')

/**
Change this macro to change the default endian format. In this example,
the default endian format is Little Endian.
*/
#define IS_DEFAULT_ENDIAN() IS_LITTLE_ENDIAN()

字节排序

计算给定数字下一个能被n整除的数

开发中需要判断给定数字是否能被n整除,如果不能被n整除则计算下一个能被n整除的数字。
例子:

#include <stdio.h>

int main()
{
    int myint = 16;
    int result = (myint + 7) & ~0x07;
    printf("%d\n",result);

    int mynum = 17;
    result = (mynum + 7) & ~0x07;
    printf("%d\n",result);

    return 0;
}

参考:
stackoverflow

我最初使用的版本如下:

#include <stdio.h>

int main()
{
    int myint = 16;
    int result = (myint + 7)/8 * 8;
    printf("%d\n",result);

    int mynum = 17;
    result = (mynum + 7)/8 * 8;
    printf("%d\n",result);

    return 0;
}

对比位运算版本效率较低,计算机的世界里位运算要远远比除法高效的多。

free内存

#define SAFE_FREE(p) if(p != NULL) {free(p); p = NULL;}

节省了代码的体量,减少重复代码。
常规写法:

if(p)
{
    free(p);
    p = NULL;
}

extern c宏

#ifdef __cplusplus
#define DECLS_BEGIN extern "C" {
#define DECLS_END   }
#else
#define DECLS_BEGIN
#define DECLS_END
#endif/*__cplusplus*/

用法示例:
在c/c++混合编程中,我们通常在c头文件中使用如下方式

ifdef __cplusplus
extern "C"{
#endif

some code stuff

#ifdef __cplusplus
}
#endif

使用我们的宏的化用法:

DECLS_BEGIN

some code stuff

DECLS_END

c语言简单单元测试框架

a minimal unit testing framework for C

源代码

/* file: minunit.h */
 #define mu_assert(message, test) do { if (!(test)) return message; } while (0)
 #define mu_run_test(test) do { char *message = test(); tests_run++; \
                                if (message) return message; } while (0)
 extern int tests_run;
 /* file minunit_example.c */
 
 #include <stdio.h>
 #include "minunit.h"
 
 int tests_run = 0;
 
 int foo = 7;
 int bar = 4;
 
 static char * test_foo() {
     mu_assert("error, foo != 7", foo == 7);
     return 0;
 }
 
 static char * test_bar() {
     mu_assert("error, bar != 5", bar == 5);
     return 0;
 }
 
 static char * all_tests() {
     mu_run_test(test_foo);
     mu_run_test(test_bar);
     return 0;
 }
 
 int main(int argc, char **argv) {
     char *result = all_tests();
     if (result != 0) {
         printf("%s\n", result);
     }
     else {
         printf("ALL TESTS PASSED\n");
     }
     printf("Tests run: %d\n", tests_run);
 
     return result != 0;
 }

执行结果:

[root minunit]#gcc -g -o minunit minunit_example.c 
[root minunit]#./minunit 
error, bar != 5
Tests run: 2