1.sizeof与strlen区别
sizeof是单目运算符,返回的是数据类型所占空间的大小,包含’\0’,单位是字节;
strlen是函数,返回的是字符串的实际长度,不包含’\0’
32位操作系统下,sizeof的几种使用情况:
//1.单纯的数据类型
sizeof(int); //4
sizeof(short); //2
sizeof(char); //1
sizeof(float); //4
sizeof(double); //8
sizeof(void); //1 网上查到的是1
//2.指针
sizeof(void *); //4
char *a="Hello World";
sizeof(a); // 4 相当于是求指针
//3.字符串
sizeof("asdfg"); //6 双引号的字符串会自动在最后补上'\0'这个字符
//4.数组
int a[9];
sizeof(a); //36,4*9=36
char b[]="hello";
sizeof(b); // 6,相当于计算sizeof("hello")
char c[50]="Hello World";
sizeof(c); // 50,返回数组的总长度
//5.函数,判断的是函数返回值类型
void* func1(char a);
sizeof(func1(1)); //4,相当于sizeof(void*)
int func2(char a);
sizeof(func2(1)); //4,相当于sizeof(int)
int func3(char a[]);
sizeof(func3); //4,相当于sizeif(int)
//6.结构体,字节对齐
struct T1{
int a;
char b;
int c;
short d;
}t1;
printf("%d", sizeof(t1); // 16; 4+4+4+4
struct T2{
int a;
char b;
short d;
int c;
}t2;
printf("%d", sizeof(t2); //12; 4+4+4
//7.联合体
union U1
{
double a;
int b;
}u1;
printf("%d", sizeof(u1); //8,u1最大成员变量double,也就相当于sizeof(double)
union U2
{
double a;
int b;
int c[10];
}u2;
printf("%d", sizeof(u2)); //40,u1最大成员变量int c[10],4*10=40,40是8的倍数,满足字节对齐
union U3
{
double a;
int b;
char c[10];
}u3;
printf("%d", sizeof(u3)); //16,u1最大成员变量char c[10],为了满足字节对齐,8的倍数,则需要变为16
2.i++,++i
int i = 1;
printf("%d ", i); //1
printf("%d ", i++); //1,此时i还未加1
printf("%d ", i); //2,i=1;i=i+1=1+1=2
printf("%d ", ++i); //3,i=2,i+1=2+1=3
int j=1;
printf("%d %d %d %d",j++,j,++j); //3 2 3 3
//这个好神奇,它会返回来更新j的值
3.unsigned int 与int 相加减计算
unsigned int a=-25;
int b=6;
printf("%d",a+b); //-19,a+b的结果看成了int型,所以为-19
(a + b > 0) ? (printf(">6")) :(printf("<=6")); //>6,unsigned int 与int相加的时候,int转化为unsigned int型,转化为二进制进行相加最高位为1,取-25的反码再和6相加,会是一个很大的值,该值大于0
4.嵌入式对寄存器赋值,位运算
寄存器赋值的时候一定要注意寄存器内值的写法是二进制还是十六进制
#define REG 0x08084
1.置位,按位操作,右边最小位为第0位
(1)将此寄存器的第2位置0
REG &=~(1<<3);
(2)将此寄存器的第3位置1
REG |=(1<<4);
2.直接赋值
long long T=0X11xx22yy;//xx,yy可以是任何值,此处用到8个字节,需要用long long型
3.将上面的寄存器T的值改为0X33xx44yy
//0X11 00010001 --> 0X33 00110011 第10位和第14位置为1
//0X22 00100010 --> 0X44 01000100 第9位和第13位置为0,第25位和第29位置为1
T &=~((1<<9)|(1<<13))
REG |=((1<<10)|(1<<14)|(1<<25)|(1<<29))
ps: printf("%x", REG);//十六进制输出
printf("%o", REG);//八进制输出
printf("%d", REG);//十进制输出
5.大小端判断
大端存储,将数据的低位保存在内存的高地址,数据的高位保存在低地址;
小端存储,将数据的高位保存在内存的高地址,数据的低位保存在低地址
#include <stdio.h>
int main() {
union {
int a;
char b[sizeof(int)];
} test;
test.a = 0x0102;
if (test.b[0] == 2) {
printf("小端");
} else if (test.b[0] == 1) {
printf("大端");
}
return 0;
}
6.static关键字
static的三种用法:
1.修饰局部变量:会改变变量的生存周期,本来变量的生存周期为代码段或函数内,static修饰后局部变量生存周期变成整个程序运行的周期;在编译的时候会在数据段为变量开辟一个空间,如果没有初始化,程序会默认初始化为0
2.修饰全局变量:全局变量是在函数体外定义的,正常的全局变量对整个工程可见,其他文件加只要使用extern就可以调用这个全局变量;static修饰后的全局变量仅对当前文件可见,其他文件不可访问,其他文件可以定义同名的全局变量,他们之间互不影响;static定义的全局变量可以避免不同文件同名变量冲突
3.修饰函数:静态函数只能在声明它的文件内被使用,工程内的其他文件不可调用;非静态函数工程内的其他的文件可以直接调用,不需要使用extern4.拓展:static不可修饰函数形参;静态变量的值是可以改变的,而且它会保持最新的值,也就是上一次调用函数时给某个变量赋了某个值,下次调用这个静态变量,它的值保持不变;auto是自动变量,动态局部变量,函数调用结束后即释放
7.嵌入式外设通信方式:SPI、IIC、UART、USB、CAN、USART
8.七种短距离通信方式:WIFI、ZigBee、蓝牙、IrDA(红外线点对点)、NFC、UWB超宽带(无限载波通信技术)
9.函数声明、函数定义、函数调用
函数声明是一个空壳,不需要实现具体的功能,例如int max(int a,int b);
函数定义必须要实现这个函数的具体功能,例如
int max(int a,int b)
{
if(a>b)
{
return a;
}
else
{
return b;
}
}
如果函数定义在函数调用之前,则不需要函数声明,反之则必须要函数声明