linux源代码中实用代码,整理出来,学习和借鉴。
常用的宏:
#define UINT_MAX (~0U)//4294967295 #define ULONG_MAX (~0UL)//4294967295 #define ULLONG_MAX (~0ULL)//18446744073709551615 #define INT_MAX ((int)(~0U>>1))//2147483647 #define INT_MIN (-INT_MAX - 1)//-2147483648 #define LONG_MAX ((long)(~0UL>>1))//2147483647 #define LONG_MIN (-LONG_MAX - 1)//-2147483648 #define LLONG_MAX ((long long)(~0ULL>>1))//9223372036854775807 #define LLONG_MIN (-LLONG_MAX - 1)//-9223372036854775808
求一个数的绝对值:
#define abs(x) ({ \ long __x = (x); \ (__x < 0) ? -__x : __x; \ })
你会遇到inet_ntoa()的重入问题,可以使用下面的代码:
/* * Display an IP address in readable format. */ #define NIPQUAD(addr) \ ((unsigned char *)&addr)[0], \ ((unsigned char *)&addr)[1], \ ((unsigned char *)&addr)[2], \ ((unsigned char *)&addr)[3] #define NIPQUAD_FMT "%u.%u.%u.%u"
交换两个数:
/* * swap - swap value of @a and @b */ #define swap(a, b) \ do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0)
判断IP地址类别:
#define IN_CLASSA(a) ((((long int) (a)) & 0x80000000) == 0) #define IN_CLASSB(a) ((((long int) (a)) & 0xc0000000) == 0x80000000) #define IN_CLASSC(a) ((((long int) (a)) & 0xe0000000) == 0xc0000000) #define IN_CLASSD(a) ((((long int) (a)) & 0xf0000000) == 0xe0000000)
hton和ntoh的实现(其实两个是调用同一个接口):
/* * casts are necessary for constants, because we never know how for sure * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way. */ #define ___constant_swab16(x) ((__u16)( \ (((__u16)(x) & (__u16)0x00ffU) << 8) | \ (((__u16)(x) & (__u16)0xff00U) >> 8))) #define ___constant_swab32(x) ((__u32)( \ (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ (((__u32)(x) & (__u32)0xff000000UL) >> 24))) #define ___constant_swab64(x) ((__u64)( \ (((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \ (((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \ (((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \ (((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) | \ (((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) | \ (((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \ (((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \ (((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56)))
是数字吗?
# define isdigit(c) ({ int __c = (c); __c >= '0' && __c <= '9'; })
面试中可能涉及字符串与整型数值之间的转换。我们知道atoi是有缺点的,内核中的strtoull实现如下(另外linux/lib/vsprintf.c中的函数也都非常不错):
#include "stdlib.h" /* Not currently supported: leading whitespace, sign, 0x prefix, zero base */ unsigned long long int strtoull(const char *ptr, char **end, int base) { unsigned long long ret = 0; if (base > 36) goto out; while (*ptr) { int digit; if (*ptr >= '0' && *ptr <= '9' && *ptr < '0' + base) digit = *ptr - '0'; else if (*ptr >= 'A' && *ptr < 'A' + base - 10) digit = *ptr - 'A' + 10; else if (*ptr >= 'a' && *ptr < 'a' + base - 10) digit = *ptr - 'a' + 10; else break; ret *= base; ret += digit; ptr++; } out: if (end) *end = (char *)ptr; return ret; }