实用C---- 记录总结 tool

本文主要介绍了C语言的一些实用工具和编程技巧,包括编译器使用、调试方法、代码优化以及常见问题的解决策略,旨在帮助开发者提高C语言编程效率和代码质量。
摘要由CSDN通过智能技术生成

struct var_data
{
	int len;
	char data[0];
}

struct var_data s;
for (i = 0; i < s.len; i++)
	printf("%02x \n", s.data[i]);
	
==================================================================================

switch (ch)
{
	case '0'... '9': c -= '0';
	break;
	case 'a'... 'f': c -= 'a' - 10;    //A 65 a 97  '' 32
	break;
	case 'A'... 'F': c -= 'A' - 10;
	break;
}

==================================================================================

#define min_t(type,x,y) \
	({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
	
int ia, ib, mini;
float fa, fb, minf;

mini = min_t(int, ia, ib);
minf = min_t(float, fa, fb);

下面一个更好的
==================================================================================


typeof(x)语句可以获得x 的类型,因此,我们可以借助typeof 重新定义min 这个宏:
#define min(x,y) ({ \
	const typeof(x) _x = (x); \
	const typeof(y) _y = (y); \
	(void) (&_x == &_y); \
	_x < _y ? _x : _y; })   //  为啥加大括号? 因为里面是一段代码。

首先,我们此处想要实现的目的是,在计算两个数的最小值之前,希望去判断一下两个值的类型是否一致,而由于C语言本身不支持我们去做类似于这样的操作typeof(_x)==typeof(_y),所以在此,通过故意判断他们2个的地址指针是否相等,而显然&_x,即x的地址,是不可能等于&_y的,但是这句话(void) (&_x == &_y);使得,如果_x和_y的类型不一样,其指针类型也会不一样,2个不一样的指针类型进行比较操作,则会引起编译器产生一个编译警告,提示你这两个值的类型不同。

(void) (&_x == &_y); 用于判断输入的两个值的类型是否是一致的。如果不一致,那么编译器就会做出如下警告:warning: comparison of distinct pointer types lacks a cast

(void) (&_x == &_y); 中的void,表示将表达式(&_x == &_y); 所得到的结果(此处肯定是逻辑上的假,值为0)忽略掉。如果不加void,则会提示你这行代码是无意义的,没人用到。

因为,如果如此定义,那么对于一些特殊的值传入此宏之后,就会产生一些副作用,产生的结果,就不是我们想要的了,比如:

  min(++a,++b) ==> ((++a)<(++b))?(++a) : (++b) 
就使得,a++和b++分别执行了2次,而且min的结果,也不对了。而用上面那个复杂的定义,多加了局部变量_x和_y,就可以避免此类问题了

==================================================================================

int printf( const char *format [, argument]... );

#define pr_debug(fmt,arg...) \
	printk(fmt,##arg)


而在GNU C 中,宏也可以接受可变数目的参数,例如:
#define pr_debug(fmt,arg...) \
	printk(fmt,##arg)
	
这里arg 表示其余的参数可以是零个或多个,这些参数以及参数之间的逗号构成 arg 的值,在宏扩展时替换 arg,例如下列代码:
	pr_debug("%s:%d",filename,line)
	会被扩展为:
	printk("%s:%d", filename, line)

	使用“##”的原因是处理arg 不代表任何参数的情况,这时候,前面的逗号就变得多余了。使用“##”之后,GNU C 预处理器会丢弃前面的逗号,这样,代码:
	pr_debug("success!\n")
	会被正确地扩展为:
	printk("success!\n")    // 没有逗号
	而不是:
	printk("success!\n",)  //多了一个逗号


	
   #define A1(name, type)  type name_##type##_type 或
   #define A2(name, type)  type name##_##type##_type

   A1(a1, int);  /* 等价于: int name_int_type; */
   A2(a1, int);  /* 等价于: int a1_int_type;   */

   至于单独一个#,则表示 对这个变量替换后,再加双引号引起来。比如

      #define  __stringify_1(x)   #x
	那么
      __stringify_1(linux)   <==>  ”linux”
	  
==================================================================================



static char *book_name = "深入浅出Linux 设备驱动";
static int num = 4000;
module_param(num, int, S_IRUGO);
module_param(book_name, charp, S_IRUGO);


参数类型可以是 byte、short、ushort、int、uint、long、ulong、charp(字符指针)、bool 或invbool(布尔的反),
在模块被编译时会将module_param 中声明的类型与变量定义的类型进行比较,判断是否一致。

insmod hello.ko num=20
则可以 cat /sys/module/hello/parameters/num ,看到为 20


1.定义模块参数的方法:
module_param(name, type, perm);
其中,name:表示参数的名字;
     type:表示参数的类型;
     perm:表示参数的访问权限;

 

2. 数组类型模块参数的定义:
用逗号间隔的列表提供的值;
声明一个数组参数:
module_param_array(name, type, num, perm);
其中,name:表示数组的名字;
     type:表示参数的类型;
     num :表示数组中元素数量;
     perm:表示参数的访问权限;

 

3.type支持的基本类型有:
bool   :布尔类型
invbool:颠倒了值的bool类型;
charp  :字符指针类型,内存为用户提供的字符串分配;
int    :整型
long   :长整型
short  :短整型
uint   :无符号整型
ulong  :无符号长整型
ushort :无符号短整型


static char *book_name = "dissecting Linux Device Driver";
static int num = 4000;

static int book_init(void)
{
	 printk(KERN_INFO " book name:%s\n",book_name);
	 printk(KERN_INFO " book num:%d\n",num);
	 return 0;
 }
 static void book_exit(void)
 {
	printk(KERN_ALERT " Book module exit\n ");
 }
 module_init(book_init);
 module_exit(book_exit);
 module_param(num, int, S_IRUGO);
 module_param(book_name, charp, S_IRUGO);


==================================================================================

Linux 2.6 的“/proc/kallsyms”文件对应着内核符号表,它记录了符号以及符号所在的内存地址。
模块可以使用如下宏导出符号到内核符号表:
EXPORT_SYMBOL(符号名);
EXPORT_SYMBOL_GPL(符号名); 。EXPORT_SYMBOL_GPL()只适用于包含 GPL 许可权的模块

cat /proc/kallsyms | grep integar
=======================&#
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值