【嵌入式八股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,万一有点用呢

全部评论
mark一下位操作
点赞 回复 分享
发布于 04-05 15:23 江苏
mark一下位操作
点赞 回复 分享
发布于 03-06 20:00 山东
接好运
点赞 回复 分享
发布于 03-04 19:21 陕西
mark一下位操作
点赞 回复 分享
发布于 03-04 19:20 陕西
接好运
点赞 回复 分享
发布于 03-03 11:31 陕西
mark一下位操作
点赞 回复 分享
发布于 03-03 11:24 陕西

相关推荐

ldf李鑫:不说公司名祝你以后天天遇到这样的公司
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
6
11
分享

创作者周榜

更多
牛客网
牛客企业服务