24、打印数据类型%02d表示显示2位数,不足补0,%2d是不足补空格;
23、全局变量是对整个工程文件有效;
22、前自增,后自增
21、 switch结构case没加break时满足case后一直执行直到遇到break,不会再比较case.
20、结构体对齐
19、定义指针的数据类型跟什么有关?
char*p;
sizeof(p)=4
sizeof(*p)=1
struct person{
char name;
int age;
}
sizeof(struct person*)=4
指针是存放地址的,大小是地址的长度,32位地址大小是4个字节,所以不管指针定义成char short int型sizeof(p)都是4,包括数组指针;定义的指针类型指的是指针指的地址存的数据的数据类型,表示从首地址开始取几个字节。
18、memcpy使用错误:赋值short型数组时数据长度写错了。
u16 AD_Value[ADC_NUM][3]; //AD采样值
u16 AD_data[ADC_NUM][3]; //AD采样值
memcpy(AD_data,AD_Value,ADC_NUM*3);这里数据应该是ADC_NUM*3*2,因为一个数据AD_Value[i][j]占两个字节。
17、再次犯了跟13条一样的错误:使用字符串函数strncat处理非字符串数组!对于非字符串数组不能使用字符串函数,因为非字符串数组里可能包含0,对于字符串函数就认为是终止符NUL就停止了!而是使用内存操作的函数,像memcpy,memset.
16、反斜杠\的用法:
在c语言中,反斜杠\一般用在语句换行或者宏定义中。
但是需要注意的是,语句换行的\加或者不加影响不大。
但是在宏定义时,如果多条语句,则必须加反斜杠,如
#define aa if (a>1) f = 0;\
else f=1;
则必须加反斜杠!
原文链接:https://blog.csdn.net/dongtuoc/article/details/79717504
15、数组作为函数形参输入时值可以被修改,如果防止被修改可以加const
14、如何定义一个字符串数组:C语言编程技巧:手把手教你如何定义及使用一个字符串数组
方法1:定义一个char类型的二维数组
这种方法是通过定义一个char类型的二维数组实现,通过二维数组的行索引可得到数组中的每个字符串,列的大小限定了每个字符串所能包含的最大字符个数,所以采用这种定义方式时,列的大小必须不能小于数组所有字符串的最大长度。如对于上面的数组,C语言的定义代码如下:
在取该数组的每个字符串时,直接对行索引即可。
方法2:定义一个指向char类型的指针数组
这种方法是通过定义一个指向char类型的指针数组实现,数组中的每个元素都是一个指针,通过该指针可得到数组中的每个字符串。如对于上面的数组,C语言的定义代码如下:
13、strncpy函数的误用:复制字符串函数,我用于复制uint8_t数组,因为数组中有0x00,函数认为是结束符就停止复制了。后改用memcpy内存复制就不会出现此问题。
12、
char Sensor_path[40];
u8 res,i;
u16 len;
char num[4];
strcpy(Sensor_path,Log_event.log_path);
strcat(Sensor_path,"/sensor");
sprintf(num,"%d",Log_event.Event_No);
// rt_kprintf ("ser_path num=%d\n",strlen(num));
strncat(Sensor_path,num,strlen(num));
strcat(Sensor_path,".txt");
rt_kprintf ("ser_path=%s\n",Sensor_path);
出现的现象是ser_path=9999.txt,
应该是ser_path=0:Log/00000002.1/20200319/sensor9999.txt
一开始以为是strlen函数输出的值不对,因为num没有\0,打印strlen(num)=4,为什么值是对的,接着打印num[4]后面的一个地址存的是什么?是\0,所以strlen输出的值是对的,又以为是num后面的空间是未使用的,所以是\0,但是用strncat结果却不对,即使num越界加了个\0也应该对呀,可能越界把Sensor_path[0]覆盖了,打印数组首地址:
Sensor_path的地址是536932176,num的地址536932172,
这就解释了为什么打印出来地址是9999.txt。
原因就是sprintf加了\0,越界了。
vs上试一下sprintf
char nwew[]="ahdndnvdkjdslfjd";
sprintf(nwew,"%s",9999);
printf("%s",nwew);
结果:9999
所以即使不nwew不清0,也会覆盖为新的字符串。
11、用sprintf函数将3转换成两位数03用%02d ,0:表示空位置填0,2表示输出域宽
sprintf( time, "%d%02d%02d",calendar.w_year,calendar.w_month, calendar.w_date);
10、strlen函数:
在vs2010
char num[4];
memcpy(num,"abc",3);
printf("%d %d",sizeof(num),strlen(num));
结果4,11
char num[4]={0};
memcpy(num,"abc",3);
printf("%d %d",sizeof(num),strlen(num));
结果:4 ,3
char num[4];
num[0]=1;
num[1]=1;
num[2]=1;
printf("%d %d",sizeof(num),strlen(num));
结果:4,15
char num[4];
num[0]=1;
num[1]=1;
num[2]=1;
num[3]='\0';
printf("%d %d",sizeof(num),strlen(num));
结果:4,3
在keil里
char num[4];
memcpy(num,"abc",3);
strlen(num)的值是3.
保险期间还是要先清空数组再用strlen,因为strlen函数就是找到\0才停止。
9、sizeof用法踩坑:
最近在使用sizeof时出的问题:以下本来是想清空数组的,实际sizeof得出来的值是4,原因是sizeof求的是指针变量的存储字节。
” 学过数据结构的你应该知道指针是一个很重要的概念,它记录了另一个对象的地址。既
然是来存放地址的,那么它当然等于计算机内部地址总线的宽度。所以在32位计算机中
,一个指针变量的返回值必定是4(注意结果是以字节为单位)“
void cleardata(uint8_t* data)
{
memset(data,0,sizeof(&data));
printf("size=%d\n",sizeof(&data));
}
1、数据类型转换:
无符号数和有符号数之间的转换不会改变存的数值、
float pitch,roll,yaw;
uint16_t g,h,t;
pitch= -124.6;
roll = -24.3;
yaw= -122.6;
g=(uint16_t)pitch;
h=(uint16_t)roll;
t= (uint16_t)yaw;
printf("%x %x %x\n",g,h,t);
输出是ff84 ffe8 ff86
keil中不能直接由float转成uint16_t,比如roll=-24.6 转成uint16_t就是24,就不带符号信息了。
2、有符号数a取反直接写-a
3、strlen函数
之前看到的说if(strlen(x)-strlen(y)>=0)或者是 if(strlen(x)-5>0)恒成立,是因为strlen函数返回的是无符号数,所以计算结果也按无符号数处理。如果改成if((short)(strlen(x)-5) >0)就是实际结果。
4、浮点数可转成4个字节传。
5.atoi函数也可以转负数
6、无符号数计算--算数转换
这两个程序的区别就是定义的数据类型不一样,结果就不一样。
原因参考:C语言中无符号数和有符号数之间的运算 - 青儿哥哥 - 博客园
C语言的三种整型数据类型:int、short int和long int - 龙猫先生 - 博客园
大概就是算术转换,int以下运算时转成int,所以第一个定义成unsigned short的程序计算时转成int型结果就是有符号数。所以“无符号数计算结果也是无符号数”这句话应该是有前提的。上面说的if(strlen(x)-strlen(y)>=0)是因为strlen返回的数据类型是unsigned int,所以结果也是unsigned int。
比如usigned int 与int型数运算,int型会转换为unsigned int与前值运算。
7、无符号数的自动回绕
测试一下自动回绕:就是无符号数加到满量程后再加就回到0.两个无符号数a b相减的含义就是a再加15个数到0xffffffff,再加就变成0,再加2就到b,所以b-a=0x12。
8、二维数组清空
uint8_t txt[6][32];
sizeof(txt) =192
用memset清空 memset(txt,0,sizeof(txt));
sizeof(txt[0]) = 32