嵌入式学习day10

一. 指针和二维数组

1.行偏移和列偏移

数组名表示数组的首地址,arr=&arr[0][0]
注意:数组名是常量,不可以实现自增或自减【arr++++arr+arr----arr】
int arr[2][3]

重点:

行偏移:
arr: 表示的第一行的行地址,偏移一整行
&arr[0]: 表示第一行的行地址,偏移一整行
在这里插入图片描述

列偏移
arr[0]: 第一行第一列的列地址,偏移一个数据类型
&arr[0][0] : 第一个元素的首地址,偏移一个数据类型
在这里插入图片描述

整体偏移
&arr: 表示整个二维数组的首地址,偏移的整个二维数组

在这里插入图片描述
在这里插入图片描述

2.二维数组 按行遍历

int main(int argc, const char *argv[])
{
  int arr[2][3] = {2, 3, 4, 5, 6, 7};
  int line = sizeof(arr) / sizeof(arr[0]);      // 行数
  int row = sizeof(arr[0]) / sizeof(arr[0][0]); // 列数
  // 按行遍历
  for (int i = 0; i < line * row; i++)
  {
    printf("%d ", arr[0][i]);     // 数组方式
    printf("%d ", *(arr[0] + i)); // 指针方式
    printf("%d ", *(&arr[0][0] + i));
  }
}

总结:arr[0][i] ===》 *(arr[0] +i) ====》*(&arr[0][0]+i)

3.二维数组 按列遍历

举例:
输出2行3列的元素
arr[1][2];

  • arr 表示第一行地址
  • arr+1 第二行的行地址
  • 加*表示降维

*(arr+1) arr[1] &arr[1][0] 表示列地址
*(arr+1)+2 表示地2行3列的地址
*( *(arr+1)+2) 表示第2行第3列的值

m行n列:
*( *(arr+m-1)+n-1 )
*(*(arr+i) +j) 表示二维数组的每个元素

for(int i=0;i<line;i++)
    {
    for(int j=0;j<row;j++)
    {
        printf("%d\t",arr[i][j]);
        printf("%d\t",*(*(arr+i)+j));//重点掌握
        printf("%d\t",*(*(&arr[0]+i)+j));
        //*(arr+i)表示i行的列地址
        //arr[i]
        printf("%d\t",*(arr[i]+j));
    }
    printf("\n");
    }

总结:a[i][j] ==> *(*(arr+i)+j) ==》 *(*(&arr[i]) +j ) ==》*(arr[i] +j)

二.数组指针

数组的指针
一般形式: int (*p)[数组长度]
本质上是一个指针,指向二维数组,或者作为形参接收二维数组地址
格式:数据类型 (*指针变量名)[常量表达式] ()>[]>*
数据类型:基本类型【int float…】 构造类型[struct union],空类型void

  • () :不可以省略
  • * :表示是一个指针
  • [] :表示数组的常量表达式:需要和指针指向的二维数组的列数保持一致
int arr[2][3];
int  (*p)[3]=arr;
     p=arr
1>一级指针和二维数组【不建议使用】
    
2>  数组指针和二维数组
int main(int argc, const char *argv[])
{
    int arr[2][3]={1,2,3,4,5,6};
    int (*p)[3]=arr;//p指向二维数组的首地址
    //行:arr &arr[0]  p &p[0]
    //列:arr[0] &arr[0][0] p[0] &p[0][0]
    /*
    printf("p=%p  p+1=%p\n",p,p+1);
    printf("&p[0]=%p &p[0]+1=%p\n",&p[0],&p[0]+1);


    printf("p[0]=%p p[0]+1=%p\n",p[0],p[0]+1);

    printf("&p=%p &p+1=%p\n",&p,&p+1);*/

    for(int i=0;i<2;i++)
    {
    

    for(int j=0;j<3;j++)
    {
    //    printf("%d\t",arr[i][j]);
    //    printf("%d\t",p[i][j]);
    //    printf("%d\t",*(*(arr+i)+j));
    //                arr=>&arr[0]
    //                arr+i=>&arr[i]
    //    printf("%d\t",*(*(p+i)+j));
    //    printf("%d\t",*(*(&arr[i])+j));
    //    printf("%d\t",*(*(&p[i])+j));
    //    printf("%d\t",*(arr[i]+j));
    //        printf("%d\t",*(p[i]+j));
    printf("%d\t",*(*p+j));
    }
    p++;
    printf("\n");
    }

    return 0;
}

int arr[2][3]; int (*p)[3]=arr;
总结:
行地址:arr ==> p ==> &arr[i] ==> &p[i]
列地址:arr[0] ==》p[0] ==》&arr[0][0] ==》&p[0][0]

取值:arr[i][j] ==》p[i][j] ===》*(*(arr+i)+j) 》*(*(p+i)+j)
*(*(&arr[i])+j) ==》*(*(&p[i])+j) ==》*(arr[i]+j) ==》*(p[i]+j)

1> 计算二维数组的和
    int Sum(int line,int row,int (*p)[row])
int Sum(int line,int row,int (*p)[row])
{
    int sum=0;
    for(int i=0;i<line;i++)
    {
    for(int j=0;j<row;j++)
    {
        printf("%d ",*(*(p+i)+j));
        sum+=*(*(p+i)+j);
    }
    }
    return sum;
}
int main(int argc, const char *argv[])
{
    int line,row;
    printf("请输入行列:");
    scanf("%d %d",&line,&row);
    int arr[line][row];

    for(int i=0;i<line;i++)
    {
    for(int j=0;j<row;j++)
    {
    //    scanf("%d",&arr[i][j]);
    scanf("%d",*(arr+i)+j);
    }
    }
    int sum=Sum(line,row,arr);
    printf("和是:%d\n",sum);
    return 0;
}
2> 计算二维数组的最大值,返回最大值
    int Max(int line,int row,int (*p)[row])

三.指针数组

指针的数组
本质上是一个数组,存储多个指针
格式: 数据类型 *指针变量名[常量表达式]
数据类型:基本类型【int float…】 构造类型[struct union],空类型void

  • * :表示是一个指针
  • 指针变量名:满足命名规范
  • [] :表示数组的
  • 常量表达式:指针的个数
1>指针数组指向多个基本类型的地址
int main(int argc, const char *argv[])
{
    int a=1,b=2,c=3,d=4;
    int *p[4]={&a,&b,&c,&d};
    
    //p[0]=&a
    //p[1]=&b
    printf("a=%p b=%p c=%p d=%p\n",&a,&b,&c,&d);
    for(int i=0;i<4;i++)
    {
    printf("%p\n",p[i]);
    printf("%d\n",*p[i]);
    }
    return 0;
}
2>指针数组指向多个数组的地址
int main(int argc, const char *argv[])
{
    int a[]={1,2};
    int b[]={3,4};
    int c[]={5,6};
    int *p[3]={a,b,c};
    //p[0]  ==>a
    //p[1] ===》b
    //输出数组a的值
//    p[0]  p[0]+1
    for(int i=0;i<2;i++)
    {
        printf("%d\t", *(p[0]+i));
    }
    return 0;
}

四.字符指针数组

本质上是一个数组,存储多个字符串的地址
格式:char *指针变量名[常量表达式]

1,存储多个字符串变量的地址


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[])
{
    char a[]="abc";
    char b[]="ABC";
    char c[]="123";
    char *p[3]={a,b,c};
    //p[0]=a
    //h
    for(int i=0;i<3;i++)
    {
    printf("%s\n",p[i]);
    printf("%s\n",*(p+i));
    }
    //把字符串b中的C字符转换D
//    p[1]  表示字符串b的第一个字符的地址
    *(p[1]+2)='D';
    printf("b=%s\n",b);


    return 0;
}

2.字符指针数组存储字符串常量的地址

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[])
{    
    //字符指针数组指向字符串常量
    
    char *q[3]={"hello","nohao","1234"};
    //q[0]="hello" 第一个字符的地址
    //q[1]="nohao" 
    for(int i=0;i<3;i++)
    {
    printf("%s\t",q[i]);
    }
    printf("\n%c\n",*(q[1]+1));
    *(q[1]+1)='i';//段错误,不可以修改只读区的常量

    return 0;
}

多级指针

一级指针:指针指向变量的地址 【数据类型 *指针变量名】
二级指针:指针指向一级指针的地址 【数据类型 **指针变量名】

多级指针:指针指向上一级指针的地址 【数据类型 *********…指针变量名】
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五.指针函数

本质是一个函数,返回是一个地址。
格式:

 数据类型  *函数名(参数列表)
    {
        return 地址;    
    }
// C语言专用模板
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
    程序要求:
*/
int *fun1() // 局部变量方式
{
    int a = 10, b = 20;
    static int arr[2] = {a, b};
    return arr;
}
int arr1[2];
int *fun2() // 全局变量方式
{
    int a = 10, b = 20;
    arr1[0] = a;
    arr1[1] = b;
    return arr1;
}
int *fun3(int *p) // 传递地址方式
{
    int a = 10, b = 20;
    *p = a;
    *(p + 1) = b;
    return p;
}
char *fun4()
{
    char *p = "hello"; // p直接指向只读字符串常量的首地址
    return p;
}
int *fun5()
{
    int a = 10, b = 20;
    int *p = (int *)malloc(sizeof(int) * 2); // 在堆区申请8个字节
    *p = a;
    *(p + 1) = b;
    return p;
}
int main()
{
    // int *p = fun1();
    // int *p = fun2();
    /*int arr[2];
    int *p=fun3(arr);*/
    /* char *q = fun4();
    printf("%s", q);*/

    int *p = fun5();

    for (int i = 0; i < 2; i++)
    {
        printf("%d ", *(p + i));
    }
    free(p); // 释放空间
    p = NULL;

    system("pause");
    return 0;
}

在这里插入图片描述

作业

作业1:实现字符串连接

char *my_strcat(char *dest, char *src)
注意:char * 表示需要返回字符串【称为指针函数】

// C语言专用模板
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
    程序要求:实现字符串连接
*/
char *my_strcat(char *dest, char *src);
int main()
{
    char str1[100] = "", str2[100] = "";
    printf("请输入字符串1\n");
    gets(str1);
    printf("请输入字符串2\n");
    gets(str2);

    printf("%s", my_strcat(str1, str2));

    system("pause");
    return 0;
}
char *my_strcat(char *dest, char *src)
{
    static char s1[100] = "";
    int i = 0, j = 0;
    while (*(dest + i) != '\0')
        i++;
    while (*(src + j) != '\0')
    {
        *(dest + i + j) = *(src + j);
        j++;
    }
    *(dest + i + j + 1) = '\0';

    return dest;
    // return *p;
}

作业2:实现字符串拷贝

char *my_strcpy(char *dest, char *src)

// C语言专用模板
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
    程序要求:实现字符串拷贝
char *my_strcpy(char *dest, char *src)
*/
char *my_strcpy(char *dest, char *src);
char *my_strcat(char *dest, char *src);
int main()
{
    char str1[100] = "", str2[100] = "";
    printf("请输入字符串1\n");
    gets(str1);
    printf("请输入字符串2\n");
    gets(str2);
    my_strcpy(str1, str2);
    puts(str1);
    system("pause");
    return 0;
}
char *my_strcpy(char *dest, char *src)
{
    int i = 0;
    while (*(src + i) != '\0')
    {
        *(dest + i) = *(src + i);
        i++;
    }
    *(dest + i ) = '\0';

    return dest;
}

作业3:.实现杨辉三角

void YangHui( int n, int (*p)[n])
提醒:
arr[i-1][j] ==> ((arr+i-1) +j )
arr[i-1][j-1] ===> *( *(arr+i-1) +j-1)

// C语言专用模板
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
    程序要求:.实现杨辉三角
void  YangHui( int n, int (*p)[n])
提醒:
arr[i-1][j]  ==> *(*(arr+i-1) +j )
arr[i-1][j-1] ===> *( *(arr+i-1) +j-1)
*/
// C语言专用模板
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
    程序要求:.实现杨辉三角
void  YangHui( int n, int (*p)[n])
提醒:
arr[i-1][j]  ==> *(*(arr+i-1) +j )
arr[i-1][j-1] ===> *( *(arr+i-1) +j-1)
*/
void YangHui(int n, int (*p)[n]);
int main()
{
    printf("请输入行列数\n");
    int n;
    scanf("%d", &n);
    int arr[n][n];
    YangHui(n, arr);
    system("pause");
    return 0;
}
void YangHui(int n, int (*p)[n])
{
    for (int i = 0; i < n; i++)
    {
        for (int a = 0; a < n - i; a++) // 输入空格
        {
            printf(" ");
        }

        for (int j = 0; j < i + 1; j++)
        {
            if (j == 0) // 第0列的数值都为1
            {
                *(*(p + i) + j) = 1;
            }
            if (i > 1 && j > 0)
            {
                *(*(p + i) + j) = *(*(p + i - 1) + j) + *(*(p + i - 1) + j - 1);
            }
            if (i == j)
            {
                *(*(p + i) + j) = 1;
            }

            printf("%d ", *(*(p + i) + j));
        }
        printf("\n");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值