11 12 13c语言编程,C语言编程

C语言编程

1.sscanf()

sscanf()与scanf()类似,都是用于输入的,只是后者以键盘(stdin)为输入源,前者以固定字符串为输入源。

头文件:#include

格式:int sscanf(const char *buffer,const char *format,[argument ]...);

举例:

char *p = "123";

int val = 0;

sscanf(p,"%d",&val);

则val == 123。

2.零长度数组

在嵌入式开发尤其是linux kernel中常用到零长度数组,可以用零长度数组成员作为可变长度数组的占位符。如以下定义:

typedef struct my_data

{

int val;

int len;

char var[0];//零长度数组成员

}data_t;

其中的成员var[0]为零长度数组,由于它的长度为零,即不占存储空间,因此以上结构体所占用的空间sizeof( struct my_data) == sizeof(val+len)。那么,var[0]成员有什么用途呢?其功能就是,我们可以定义可变长度的数组,并通过var[i]访问该结构体中成员len之后的第i个数据。

如下所示:

#define LEN10

data_t *test = malloc(sizeof(data_t)+LEN);

test->var[8] = 5;//访问另外LEN内的数据

3.extern修饰函数 在头文件中声明函数或者在C文件中定义函数时,加不加extern都是相同的,因为在这两种情况下,函数默认就是extern的。

4.数组名不等于函数指针

比如, 我们可以通过sizeof()计算数组的长度:

char  p[100];

sizeof(p) = 100;

char *p;

sizeof(p)=4;

因此,注意数组名与函数指针之间的差异。

5.计算结构体中元素的偏移 如定义了一个结构体

struct OffsetTest

{

char a;//offset->0

char b;//offset->1

char c;//offset->2

char d;//offset->3

int e;//offset->4

int f;//offset->8

};则可以通过如下定义的宏计算结构体中任意一个元素的相对偏移:

#define OFFSET_OF(struct_name, field) ((int)&((struct_name *)0)->field)而计算结构体的大小可以直接用sizeof()运算符计算。

6.itoa() 和atoi()函数

itoa():将整型值转换为字符串,atoi()则实现相反的操作。

在不支持这两个库函数的系统中,可以自己编写类似功能的函数。如下所示:

int my_atoi(char *str)

{

int i = 0,ret = 0;

ret = (*str++ - '0');

while(*str)

{

ret = ret*10 + (*str - '0');

str++;

}

return ret;

}

7.循环移位操作

#define ROTATE_LEFT(x,n) ((x) << (n)) | ((x) >> (sizeof(x)*8 - (n)))

#define ROTATE_RIGHT(x,n) ((x) >> (n)) | ((x) << (sizeof(x)*8 - (n)))

8.strcpy()、 strncpy()与strlcpy()

A.strcpy()

strcpy()在拷贝字符串时,以"\0"为结束标志,如果源字符串不以“\0”结尾,则程序会陷入死循环。而如果目的地址的存储空间比源字符串长度小的话,还会造成内存溢出。因此,strcpy()的使用存在一定的安全问题,使用时要谨慎。

B.strncpy()

strncpy()相对于strcpy()而言相对安全,但当源字符串中字符数量(不含末尾的0)于目的空间大小相等时,不能保证在目的地址后补0,因此,使用strncpy()时标准的做法是在拷贝完成后,在目的字符串的末尾填充0。

C.strlcpy()

strlcpy()不是ANSI C中的标准内容,但是linux中经常用到。这个函数能够保证最多拷贝目的空间大小减去一个字符,并会在末尾自动补0,因此更安全。

9.求整数N的阶乘(n!)

unsigned int factorial(unsigned int n)

{

unsigned int result = 0;

if(n >= 2)

{

return n*factorial(n-1);

}

return 1;

}

10.逗号的用法

A.逗号作为逗号运算符,构成逗号表达式,又称顺序求值运算符

此种情况,从左到右依次求解各个表达式的值,整个逗号表达式的值最终等于最右边的表达式的值,如下:

int a = 1,b = 2;

printf("Result = %d!\n",(a = b+a,a));如,上述代码执行的结果为3。

B.逗号作为分隔符

在printf函数中,对参数的计算顺序是从右往左的。

如下:

int a = 1,b = 2;

printf("Result = %d,%d,%d,%d!\n",a,b,a += b,b += a);上述代码的运行结果为3,4,3,4。

11.宏中定义局部变量以及通过宏函数获取返回值

#define get_val(n)\

({\

unsigned int v;\

if (n > 100)\

v = 1;\

else\

v = 0;\

v;\

})

12.可变个数参数的宏函数

#define LOG(fmt,arg...)printf(fmt,##arg)

13.fflush()和fsync()

int fflush(FILE *stream):只能将数据刷到文件系统的缓存中,并没有真正写到存储介质里。

int fsync(int fd):才会把数据刷新到存储介质里。

但是因为fsync()的参数为文件描述符,当通过fopen()打开文件时,需要将文件流指针转换为文件描述符,可以通过fileno()函数进行转换。

14.内存地址对齐

在编程过程中,或者需要对程序进行优化时,经常需要用到地址须按字对齐的变量或数组等,如下面语句中的关键字__align(4) 用于使定义的数组的首地址按4字节对齐:

__align(4) uint8_t DataBuf[2048];

15.头文件的应用

static CommandInfo commands[] = {

#include "my_commands.h"

};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值