嵌入式开发学习(第二阶段 C语言基础)

发布于:2025-05-27 ⋅ 阅读:(46) ⋅ 点赞:(0)

指针

数组指针与指针数组

数组指针
指针和数组中符号优先级
()  > []  > *
通过指针引用二维数组
表示形式 含义 地址/值
a 二维数组名,指向一维数组a[0] (0行首地址) 2000
a[0],*(a+0 ),*a 0行0列元素地址 2000
a + 1,&a[1] 1行首地址 2008
a[1], *(a + 1) 1行0列元素a[1] [0]的地址 2008
a[1],*(a+1)+2,&a[1][2] 1行2列元素a[1] [2]的地址 2012
*(a[1]+2),*(*(a+1) +2),a[1][2] 1行2列元素a[1] [2]的值 元素值为13

注意:二维数组中,数组整体的地址值 == 数组中0行元素的地址值 == 数组中0行0列元素的地址 值

在这里插入图片描述

案例

案例1

  • 需求:用指向元素的指针变量输出二维数组的值

  • 代码:

    /*************************************************************************
      > File Name:    demo02.c
      > Author:       小刘
      > Description:  
      > Created Time: 2025年05月21日 星期三 11时44分03秒
     ************************************************************************/
    
    #include <stdio.h>
    
    int main(int argc,char *argv[])
    {
        // 定义一个二维数组
        int arr[3][4] = {10,20,30,40,100,200,300,400,1000,2000,3000,4000};
    
        // 定义一个指针变量,用来接收二维数组的元素
        int *p = arr[0];
        
        // 获取元素的个数
        int len = (sizeof(arr)/sizeof(arr[0]) * sizeof(arr[0])/sizeof(arr[0][0]));
        //遍历数组
        //通过指针变量访问二维数组,只需要一层for循环
        for(;p <arr[0] +len ; p++)
        {
            //每四行换行
            if((p - arr[0]) % 4 == 0 && p != arr[0])printf("\n");
            printf("%-6d",*p);
        }
        printf("\n");
        return 0;
    }
    
案例2:
  • 需求:数组指针- 输出二维数组任一行任意列元素的值

  • 代码:

    /*************************************************************************
      > File Name:    demo03.c
      > Author:       小刘
      > Description:  
      > Created Time: 2025年05月21日 星期三 12时00分44秒
     ************************************************************************/
    
    #include <stdio.h>
    
    int main(int argc,char *argv[])
    {
        // 定义一个二维数组
        int arr[3][4] = {1,3,5,7,11,33,55,77,111,333,555,777};
        
    	//创建一个数组指针指向二维数组
        int (*p)[4] = arr; // 二维数组中的第一个元素就是首行
    
        // 创建两个变量,接收控制台输入的行和列
        int row, col;
    
        printf("请输入行号和列号:\n");
        scanf("%d,%d",&row,&col);
        printf("arr[%d][%d]=%d,%d,%d,%d\n",row,col,*(*(p+row)+col),(*(p+row))[col],*(p[row]+col),p[row][col]);
        return 0;
    }
    
指针数组

**定义:**指针数组是一个数组,数组中每一个元素都是一个指针。

特点:

  • 现有指针后又数组
  • 指针数组的本质是一个数组,只是数组元素类型是指针。

语法:

数据类型  *数组名[容量]

案例:

/*************************************************************************
  > File Name:    demo04.c
  > Author:       小刘
  > Description:  
  > Created Time: 2025年05月21日 星期三 14时16分51秒
 ************************************************************************/

#include <stdio.h>

int main(int argc,char *argv[])
{
    //定义三个变量
    int a = 10,b = 20, c = 30;

    // 定义指针数组,指针数组是用来存储指针的
    int *arr[3] = {&a,&b,&c};

    // 获取数组大小
    int len = sizeof(arr) / sizeof(arr[0]);

    //遍历数组
    for(int i = 0;i < len; i++)
    {
        printf("%-3d",*arr[i]);//arr先跟[]结合取出地址,地址再跟左侧×结合,解引用出地址对应空间的数据
    }
    printf("\n");
    
    return 0;
}

建议:我们一般使用指针数组处理字符串。

数据指针与指针数组的区别
对比项 指针数组 数组指针
定义 数组元素均为指针的数组 指向一个完整数组的指针
存储内容 存储多个指针,每个元素指向不同内存地址 存储单个指针,指向一个完整的数组(首地址)
内存分配 每个指针元素独立分配内存,可能分散 指向的数组内连续,指针本身存储数组首地址
语法示例 int *arr[5];(元素为5个int *指针) int (*ptr)[5];(指向含5个int数组的指针)
访问方式 通过下标访问指针元素,再解引用:*arr[i] 先解引用指针得到数组,再访问元素:(*ptr)[i]或ptr[0][i]
使用场景 管理多个独立指针(如字符串数组、动态结构体数组) 操作多维数组(如传递二维数组的行指针)
内存布局示意图 [ptr1] → 数据1 [ptr2] →数据2… ptr → [数据1] [数据2] [数据3] [数据4] [数据5 ]
示例代码 int a=1, b=2;int *arr[]<b= {&a, &b}; int arr[2][3] ={1,2,3,4,5,6};int (*ptr)[3] =arr

字符数组和字符指针

字符串的实现
char atr[20] = "李白";
char *str = "李白"

在C语言中,表示一个字符串有以下两种方式:

①数组形式:用字符数组存放一个字符串

②指针形式:用字符指针存放一个字符串

/*************************************************************************
  > File Name:    demo06.c
  > Author:       小刘
  > Description:  
  > Created Time: 2025年05月26日 星期一 21时56分23秒
 ************************************************************************/

#include <stdio.h>

/**
* 方式1:使用字符数组实现字符串
*/
void str_test1()
{
    // 定义一个伪字符串
    char str[] = "I LOVE YOU";
    printf("%s\n",str);
}


/**
* 方式2:使用字符指针实现字符串
*/
void str_test2()
{
    // 定义一个伪字符串
    char *str = "I LOVE YOU";
    printf("%s\n",str);
}

int main(int argc,char *argv[])
{
    str_test1();
    str_test2();
    return 0;
}

注意:字符数组和字符指针变量都能实现字符串的存储与运算。(字符指针---->字符类型的指针变量)

字符数组和字符指针的联系
概念
  • 字符数组由元素组成,每一个元素存放一个字符:而字符指针(变量)中存放的是地址(可以作为函数参数)
char str[] = {'i','0'};
  • 只能对字符数组中元素赋值,而不能用赋值语句对整个字符数组赋值。

    char arr[3] ={};
    arr[2] = 'A';    //正确,对字符数组中的元素赋值
    
    arr = {'E','D','F'};//错误,对整个数组赋值(可以理解为数组名就是一个常量,一旦创建就无法改变)
    
  • 字符数组虽然代表地址,但数组名的值不能改变,因为数组名是常量。

  • 对于字符串中的存取,可以用下标法,也可以用指针法。

案例
/*************************************************************************
  > File Name:    demo05.c
  > Author:       小刘
  > Description:  
  > Created Time: 2025年05月21日 星期三 14时58分20秒
 ************************************************************************/

#include <stdio.h>

int main(int argc,char *argv[])
{
    // 使用两种方式创建字符串
    char str1[] = "你好,中国!";
    char *str2 = "你好,陕西!";


    // 赋值测试
    // str1 = "你好,未来";//错误,数组一旦创建,就无法改变其值
    str2 = "创新未来";

    printf("%s,%s\n",str1,str2);


    //char *str;
    printf("请输入一个字符串:\n");
    scanf("%s",&str);
    printf("输出-%s\n",str);

    char a[] = "I LOVE CHIAN";
    char *b = "I LOVE CHINA";

    printf("%c,%c\n%c,%c\n%s,%s\n",a[2],*(a+2),b[2],*(b+2),a+2,b+2);
    return 0;
}
字符串作为形式参数

定义:

  • 实参与形参都可以是字符数组

    void fun(char str[], int len){..} 
    void main()
    {
        char str[] = "hello";
    	int len = sizeof(str)/sizeof(str[0]); 
        fun(str,len);
    }
    
  • 实参用字符数组,形参用字符指针

    void fun(char *str, int len){..} 
    void main()
    {
        char str[] = "hello";
    	int len = sizeof(str)/sizeof(str[0]); 
        fun(str,len);
    }
    
  • 形参和实参都是指针(在函数内部不能对字符串中的字符做修改

    #include <stdio.h>
    void fun(char *str, int len)
    {
    	// 在函数内部不能对字符串中的字符做修改,否则报错 段错误
    	// *(str+1) = 'E';
    	// str[2] = 'L';
    	printf("%s\n",str); // hELlo
    } 
    int main(int argc,char *argv[])
    {
    	char *str = "hello";
    	int len = sizeof(str)/sizeof(str[0]);
    	fun(str,len);
    	return 0;
    }
    
  • 实参是指针类型形参是字符数组

    #include <stdio.h>
    void fun(char str[], int len)
    {
    	// 在函数内部不能对字符串中的字符做修改,否则报错 段错误
    	// *(str+1) = 'E';
    	// str[2] = 'L';
    	printf("%s\n",str); // hELlo
    } 
    int main(int argc,char *argv[])
    {
    	char *str = "hello";
    	int len = sizeof(str)/sizeof(str[0]);
    	fun(str,len);
    	return 0;
    }
    

注意:

  1. 字符数组在创建的时候,会在内存中开辟内存空间,内存空间可以存放字符数据;字符指针在创建的时候,需要依赖于字符数组,字符指针在内存开辟的内存空间中,存放的是数组元素的地址。字符指针的创建依赖于字符数组,字符数组可以独立存在,而字符指针不能独立存在。

  2. 字符数组可以初始化,但是不能赋值;字符指针可以初始化,也可以赋值。

    char str1[] = "helllo";//对数组初始化
    str1 = "hi";     //对数组赋值,此时错误
    
    str[0] = 'h';    //对数组中的元素赋值,此时正确
    
案例

案例1

  • 需求:字符指针作为函数参数:用函数调用实现字符串的复制以及长度计算
  • 代码:
/*************************************************************************
  > File Name:    demo07.c
  > Author:       小刘
  > Description:  
  > Created Time: 2025年05月21日 星期三 16时14分24秒
 ************************************************************************/

#include <stdio.h>

int str_cpy(const char *source,char *target)
{
    register int i = 0;
    while(source[i] != '\0')
    {
        *(target + i) = *(source + i);

        i++;
    }
    *(target + i) = '\0';
    return i;
}

int main(int argc,char *argv[])
{
    char source[20],target[20];

    scanf("%s",source);
    
    int len = str_cpy(source,target);
    printf("字符串:%s的长度为:%d\n",source,len);
    return 0;
}

运行结果:

在这里插入图片描述

案例2
  • 需求:字符指针作为函数的参数- 给定一个字符串

  • 代码::

    /*************************************************************************
      > File Name:    demo08.c
      > Author:       小刘
      > Description:  
      > Created Time: 2025年05月21日 星期三 16时27分46秒
     ************************************************************************/
    
    #include <stdio.h>
    
    /**
     * 定义一个函数,实现字符串的截取
     * @param source 源字符串
     * @param start  开始位置
     * @param end    结束位置
     * @param target 目标字符串
     * @return 目标字符串长度
     */
    int str_substr(char *source,int start,int end,char *target)
    {
        register int i = 0,k = 0;
        // 遍历源字符串
        while (source[i] != '\0')
        {
            // 根据start和end截取
            if(i >= start && i < end)
            {
                *(target + k) = *(source + i);
                k++;
            } 
            i++;
        } 
        *(target + k) = '\0';
        return k;
    }
    
    int main(int argc,char *argv[])
    {
        char *str = "abcdefg";// cde
        char target[26];
        int len = str_substr(str,2,5,target);
        printf("%s,%s,%d\n",str,target,len);
        return 0;
    }