linux实用代码

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

 

你可能感兴趣的:(linux实用代码)