《嵌入式C语言笔记(十五):字符串操作与多维指针深度解析》

发布于:2025-07-31 ⋅ 阅读:(26) ⋅ 点赞:(0)

1.字符串与指针安全操作

函数

函数 功能 安全替代 功能
strcpy 字符串拷贝 strncpy 复制前n个,最多strlen个,超出有效长度,按原样复制
strcat 字符串拼接 strncat dest只连接src的前n个,如果n超过有效长度,按原样链接
strcmp 字符串比较 strncmp 比较前n个字符
strlen 获取有效长度(不含\0

const关键字与万能指针

const关键字

        1.普通变量经过const修饰后,会变为只读变量,无法直接访问,只能通过间接访问修改。
        2.指针变量前加const,不是说p不能改,而是*p不能改(p指向的变量),修饰的是*p(无法通过指针运算修改指针变量所指向的变量)

void*万能指针

  • 可接收任意基类型指针,但不能做指针运算,可以降低程序的耦合性。
  • 需强制类型转换。

2.数组指针与指针数组

数组指针(指向数组的指针)

  • 定义:指向数组的指针,括号不能省略,一维数组使用时,p+1为野指针。二维数组使用p + 1,不是野指针(二维数组作为函数参数传递,形参是指向一维数组的指针)。
  • int (*p)[4](指向含4个整数的数组)

3.函数与指针

指针函数(返回指针的函数)

  • 禁止返回局部变量的地址,可以返回局部变量的值。
// 错误示例
int* func() {
    int a = 10;
    return &a;  // a销毁后返回野指针
}

  • 安全返回,用static修饰为静态变量,或者直接用全局变量。
int* safe_func() {
    static int b = 20;  // 静态存储期
    return &b;          // 合法
}

4.关键技巧总结

  1. 字符串常量,内容相同时,地址是一样的
  2. void*使用规范
    • 用于内存拷贝memcpy函数
    • 用前必须强制类型转换
  3. const最佳实践
    • 函数参数加const防止意外修改(如strlen(const char*))

4.代码

        1)字符串的操作

        

void Puts(const char *s)
{
    while(*s)
    {
        putchar(*s++);
    }
    puts("");
}

int Strlen(const char *s)
{
    int counter = 0;
    while(*s)
    {
        ++counter;
        ++s;
    }
    return counter;
}

void Strcpy(char *dest, const char *src)
{
    while(*src)
    {
        *dest++ = *src++;
    }
    *dest = 0;
}

void Strcat(char *dest, const char *src)
{
    while(*dest)
    {
        ++dest;
    }
    while(*src)
    {
        *dest++ = *src++;
    }
    *dest = 0;
}

int Strcmp(const char *s1,const char *s2)
{
    while(*s1 == *s2 && *s1 && *s2)
    {
        ++s1;
        ++s2;
    }
    return *s1 - *s2;
}

void Strncpy(char *dest, const char *src, int n)
{
    while(n--)
    {
        *dest++ = *src++;
    }
    *dest = 0;
}

void Memcpy(void *dest, const void *src, int n)
{
    char *p = (char *)src;
    char *q = (char *)dest;
    while(n--)
    {
        *q++ = *p++;
    }
    *q = 0;
}

void Strncat(char *dest, const char *src, int n)
{
    while(*dest)
    {
        ++dest;
    }
    while(n-- && *src)
    {
        *dest++ = *src++;
    }
    *dest = 0;
}

int Strncmp(const char *s1, const char *s2, int n)
{
    while(--n && *s1 == *s2 && *s1 && *s2)
    {
        ++s1;
        ++s2;
    }
    return *s1 - *s2;
}

int main(void)
{
    char s1[100] = "Hello";
    char s2[100] = "Helloq";

    //Puts(s1);
    
    //printf("%d\n", Strlen(s1));

    //Strcpy(s2, s1);
    //Puts(s2);

    //Strcat(s1, s2);
    //puts(s1);

    //printf("%d\n",Strcmp(s1,s2));

    //Strncpy(s2, s1, 5);
    //Puts(s2);

    //Memcpy(s2, s1, sizeof(s1));
    //Puts(s2);
    
    //Strncat(s2, s1, 8);
    //Puts(s2);

    //printf("%d\n", Strncmp(s1, s2, 5));

    return 0;
}
        2)二维数组的操作(数组指针)
void printfArray2D(int (*a)[4], int rows)
{
    int i, j;
    for(i = 0;i < rows;++i)
    {
        for(j = 0;j < 4;++j)
        {
            printf("%2d ", *(*(a + i) + j));
        }
        puts("");
    }
}

int sumOfArray2D(int (*a)[4], int rows)
{
    int i,j;
    int sum = 0;
    for(i = 0;i < rows;++i)
    {
        for(j = 0;j < 4;++j)
        {
            sum += *(*(a + i) + j);
        }
    }
    return sum;
}

void swap(int *a, int *b)
{
    int t = *a;
    *a = *b;
    *b = t;
}

void reverse(int *begin, int *end)
{
    while(begin < end)
    {
        swap(begin, end);
        ++begin;
        --end;
    }
}

void reverse2D(int (*a)[4], int rows)
{
    int i;
    for(i = 0;i < rows;++i)
    {
        reverse(*(a + i),*(a + i) + 4 - 1);
    }
}




int main(void)
{
    int a[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    int rows = sizeof(a) / sizeof(a[0]);


    //printfArray2D(a, rows);

    //printf("%d\n", sumOfArray2D(a, rows));

    //reverse2D(a, rows);
    //printfArray2D(a, rows);


    return 0;
}

3)指针函数
char *Strcat(char *dest, const char *src)
{
    char *ret = dest;
    while(*dest)
    {
        ++dest;
    }
    while(*src)
    {
        *dest++ = *src++;
    }
    *dest = 0;
    return ret;
}

5.总结

  1. 字符串操作strn系列函数更安全。
  2. 嵌入式安全
    • const保护只读数据(如固件配置)
    • 静态变量/全局变量保障指针生命周期

关联知识:结合内存分区理解指针生命周期(栈/静态区/堆)


网站公告

今日签到

点亮在社区的每一天
去签到