【嵌入式八股8】基础语法
一、strcmp 函数
strcmp
函数用于比较两个字符串的大小,其返回值反映了两个字符串的大小关系:
- 若字符串 1 等于字符串 2,返回值等于 0;
- 若字符串 1 大于字符串 2,返回值大于 0;
- 若字符串 1 小于字符串 2,返回值小于 0。
该函数的比较规则是按照字符的 ASCII 码值逐个比较两个字符串中的字符,直到遇到不同的字符或者字符串结束符 '\0'
。示例代码如下:
#include <stdio.h>
#include <string.h>
int main() {
char str1[] = "abc";
char str2[] = "abc";
char str3[] = "abd";
int result1 = strcmp(str1, str2);
int result2 = strcmp(str1, str3);
printf("str1 和 str2 比较结果: %d\n", result1);
printf("str1 和 str3 比较结果: %d\n", result2);
return 0;
}
二、位操作
在嵌入式开发中,位操作是非常常见的操作,通过位操作可以高效地对数据的某一位或某几位进行读取、设置或清除。以下是几个常用的位操作宏定义:
// 获取 x 的第 bit 位的值(0 或 1)
#define GetBit(x, bit) (((x) & (1 << (bit))) >> (bit))
// 将 x 的第 bit 位置 1
#define SetBit(x, bit) ((x) |= (1 << (bit)))
// 将 x 的第 bit 位清 0
#define ClrBit(x, bit) ((x) &= ~(1 << (bit)))
使用示例:
#include <stdio.h>
int main() {
int num = 0x0A; // 二进制 1010
int bit = 1;
// 获取第 1 位的值
int bitValue = GetBit(num, bit);
printf("第 %d 位的值为: %d\n", bit, bitValue);
// 设置第 2 位为 1
SetBit(num, 2);
printf("设置第 2 位为 1 后的值: 0x%x\n", num);
// 清除第 3 位为 0
ClrBit(num, 3);
printf("清除第 3 位为 0 后的值: 0x%x\n", num);
return 0;
}
三、寄存器操作
在嵌入式系统中,经常需要对寄存器进行操作。使用联合体(union
)可以方便地对寄存器的不同位域进行访问。以下是一个示例:
#include <stdio.h>
#include <stdint.h>
typedef union Reg {
uint32_t Byte;
struct {
uint32_t a : 16; // bit [0 - 15]
uint32_t b : 8; // bit [16 - 23]
uint32_t c : 1; // bit 24
uint32_t d : 4; // bit [25 - 28]
uint32_t e : 1; // bit 29
uint32_t f : 1; // bit 30
uint32_t g : 1; // bit 31
};
} Reg; // 占用 uint32_t 大小空间
// usage
int main() {
Reg misc;
misc.Byte = 0xffff0000;
misc.a = 0xaa;
printf("0x%x\n", misc.Byte);
return 0;
}
// 执行结果:0xffff00aa
在上述代码中,通过联合体 Reg
可以直接对 Byte
进行整体操作,也可以通过结构体成员对不同的位域进行操作。
四、运算符优先级
在 C 语言中,运算符的优先级决定了表达式中各个运算符的计算顺序。如果一个表达式中的两个操作数具有相同的优先级,那么它们的结合律(associativity)决定它们的组合方式是从左到右或是从右到左。以下是 C 语言中常见运算符的优先级和结合律:
1 | () |
带括号的表达式 | 从左至右 |
[] |
数组下标 | 从左至右 | |
. |
按对象选择成员 | 从左至右 | |
-> |
按指针选择成员 | 从左至右 | |
+ - |
一元加、一元减 | 从右至左 | |
++ -- |
递增、递减(前缀形式) | 从右至左 | |
2 | ! ~ |
逻辑非、按位补 | 从右至左 |
* |
取消引用(也称为间接运算符) | 从右至左 | |
& |
寻址符 | 从右至左 | |
sizeof |
表达式或者类型所占的字节数 | 从右至左 | |
(type) |
强制类型转换,如 (int)a |
从右至左 | |
3 | * / % |
乘、除、取余数 | 从左至右 |
4 | + - |
加、减 | 从左至右 |
5 | << >> |
按位左移、按位右移 | 从左至右 |
6 | < <= |
小于、小于等于 | 从左至右 |
> >= |
大于、大于等于 | 从左至右 | |
7 | == != |
等于、不等于 | 从左至右 |
8 | & |
按位与 | 从左至右 |
9 | ^ |
按位异或 | 从左至右 |
10 | ` | ` | 按位或 |
11 | && |
逻辑与 | 从左至右 |
12 | ` | ` | |
13 | ?: |
条件运算符 | 从右至左 |
= |
赋值 | 从右至左 | |
+= -= |
加法赋值、减法赋值 | 从右至左 | |
14 | *= /= |
乘法赋值、除法赋值 | 从右至左 |
%= |
取余数赋值 | 从右至左 | |
<<= >>= |
按位左移赋值、按位右移赋值 | 从右至左 | |
`&= | =` | 按位与赋值、按位或赋值 | |
^= |
按位异或赋值 | 从右至左 | |
15 | , |
逗号运算符 | 从左至右 |
五、*ptr++
相关操作
*
和 ++
运算符的组合使用在指针操作中较为常见,它们的优先级和结合性会影响操作的结果。以下是一些示例代码:
#include <stdio.h>
int main() {
int num[] = {1, 3, 5, 7, 9};
int* ptr_num = num;
// 先对指针移位地址加 1,然后解引用
printf("%d\n", *++ptr_num);
// 先解引用,再对数值 +1
printf("%d\n", ++*ptr_num);
// * 与 ++ 优先级相同,右边先运算,但因为是后 ++,因此先解引用输出 1,然后对指针 ++,指向第二个元素
printf("%d , %d\n", *ptr_num++, *ptr_num);
// 先解引用取值,修改值 ++
printf("%d , %d\n", (*ptr_num)++, num[0]);
int a[5] = {0, 1, 2, 3, 4};
int *ptr = a;
printf("%d\n", *ptr);
printf("%d\n", *ptr++);
printf("%d\n", *ptr);
printf("%d\n", *++ptr);
printf("%d\n", *ptr);
return 0;
}
// 输出结果:
// 3
// 4
// 4 , 5
// 5 , 1
// 0
// 0
// 1
// 2
// 2
在实际应用中,*ptr++
常用于遍历数组等场景。例如,在计算 CRC 校验和的函数中:
#include <stdio.h>
#define CRC8_TAB_SIZE 256
unsigned char CRC8_TAB[CRC8_TAB_SIZE];
unsigned char Get_CRC8_Check_Sum(unsigned char *pchMessage, unsigned int dwLength, unsigned char ucCRC8) {
unsigned char ucIndex;
while (dwLength--) {
ucIndex = ucCRC8 ^ (*pchMessage++); // 先取指针的指向的值,使用完后指针自增
ucCRC8 = CRC8_TAB[ucIndex];
}
retu
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
嵌入式八股/模拟面试拷打 文章被收录于专栏
一些八股模拟拷打Point,万一有点用呢