http://ask.wosoni.com/q/6169393.html
“code”关键字 51特有
有这样一种数据,我们在程序中要使用,但是却不会改变它的值,定义这种数据时可以加一个 code 关键字修饰一下,这个数据就会存储到我们的程序空间 Flash 中,这样可以大大节省单片机的 RAM 的使用量,毕竟我们的单片机 RAM 空间比较小,而程序空间则大的多。那么现在要使用的数码管真值表,我们只会使用它们的值,而不需要改变它们,就可以用 code 关键字把它放入 Flash 中了 。
字符串格式
可以定义const常量,具有不可变性
const Uchar lengthF1=6; //字符串长度
\r是reurn的意思 \n是newline的意思\r
在windows下,实际你按下回车键的时候是回车加换行的作用,所以在串口助手里面,单片机给它发送要有\r\n才相当于你按下回车键
return理解为回到开头,newline理解为新的一行,如果只是新行,是不行的哦,要回到行首才行
printf("%x\n", j); //输出结果为: 2f
printf("%X\n", j); //输出结果为: 2F
printf("%#x\n", j); //输出结果为: 0x2f
printf("%#X\n", j); //输出结果为: 0X2F %#X推荐使用
字符串分割函数strtok
在第一次调用时,strtok()必需给予参数s字符串,往后的调用则将参数s设置成NULL。每次调用成功则返回指向被分割出片段的指针。
#include "stdio.h"
#include "string.h"
int main()
{
// printf("%%\n");
// int a=183;
// printf("%.2f\n",(float)a/100);
// int a=78;
// char * str;
// sprintf(str,"%d%%",a);
// puts(str);
char a[100]="温度24度,*,注意防止中暑。",b[]="湿度为70%",c[500];
sprintf(c,"%s%s",strtok(a,"*"),b);
strcat(c,strtok(NULL,"*"));
puts(c);
return 0;
}
可变参数原理
参考链接:http://www.runoob.com/cprogramming/c-macro-va_start.html
https://www.cnblogs.com/a-flydog/articles/5967850.html
- va_list表示可变参数列表类型,实际上就是一个char指针;
- va_start用于获取函数参数列表中可变参数的首指针(获取函数可变参数列表);
- va_arg用于获取当前ap所指的可变参数并将并将ap指针移向下一可变参数;
- va_end用于结束对可变参数的处理。
对可变参数列表的处理过程一般为:
- 用va_list定义一个可变参数列表;
- 用va_start获取函数可变参数列表;
- 用va_arg循环处理可变参数列表中的各个可变参数;
- 用va_end结束对可变参数列表的处理。
举例如下:
#include
#include
int sum(int num_args, ...)
{
int val = 0;
va_list ap; //初始化 ap 变量,ap 用来保存第一个可变参数的地址
int i;
va_start(ap, num_args); //va_start 使 num_args 指向第一个可选参数
for(i = 0; i < num_args; i++)
{
val += va_arg(ap, int); //用于获取当前ap所指的可变参数,并将ap指针移向下一可变参数
}
va_end(ap); //va_end 把 num_args 指针清为NULL
return val;
}
void main(void)
{
printf("1、2、3、4 和 5 的和为 %d。\n", sum(5, 1, 2, 3, 4, 5) );
}
vsprintf
函数名: vsprintf
- 返回值: 正常情况下返回生成字串的长度(除去\0),错误情况返回负值
用 法: int vsprintf(char *string, char *format, va_list param);//将param 按格式format写入字符串string中
- 注: 该函数会出现内存溢出情况,建议使用vsnprintf
#include
#include
char buffer[80];
int vspf(char *fmt, ...)
{
va_list argptr;
int cnt;
va_start(argptr, fmt);
cnt = vsprintf(buffer, fmt, argptr); //不同格式字符拼接,返回字符串的长度
va_end(argptr);
return(cnt);
}
int main(void)
{
int inumber = 30;
float fnumber = 90.0;
char string[4] = "abc";
int cnt;
cnt = vspf("%d %f %s", inumber, fnumber, string);
printf("%s\n", buffer);
printf("%d\n", cnt);
return 0;
}
变量的储存类别
- auto (自动的)
- static (静态的)
- register (寄存器的)
- extern (外部的)
其中 auto 和 register 声明的变量属于动态存储方式,static 和 extern 声明的变量属于静态存储方式。
特别说明: 关键机 auto 可以省略,auto不写则默认为“自动存储类别”;auto int i;
与 int i;
等价。
字符串转十进制("1252" → 1252D)
//处理Gap=0252mm(Gap 间隔)
#include
void main()
{
char string[] = "Gap=1252mm"; //串口得到的数据
int i, result[4], sum = 0;
if(string[4]>='0' && string[4]<='9')
{
for(i=4; i<8; i++)
result[i-4] = string[i]-'0';
sum = result[0]*1000+result[1]*100+result[2]*10+result[3];
}
printf("距离%dmm\r\n", sum);
}
结构体大小的计算
https://www.cnblogs.com/lykbk/archive/2013/04/02/krtmbhrkhoirtj9468945.html
结构体计算要遵循字节对齐
原则
结构体默认的字节对齐一般满足三个准则:
-
- 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
-
- 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
3. 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)
其实 暂且不管这三原则,我的方法只要记住第三个,就是结构体大小结果要为成员中最大字节的整数倍
struct { char a; short b; char c; }S1;
struct { char a; char b; short c; }S2;
分别用程序测试得出sizeof(S1)=6 , sizeof(S2)=4
C语言初始化一个全局变量或static变量时,只能用常量赋值,不能用变量赋值!