day7嵌入式(2022.1.13)

简介: day7嵌入式(2022.1.13)

数组指针,指针数组


#include<stdio.h>
int main()
{
  int a = 100;
  int *p1 = &a; // 整型指针
  char ch = 'A';
  char *p2 = &ch; // 字符型指针
  int arr[5] = {1, 3, 5, 7, 9};
  int *p3 = arr;  // 整型指针,指向整型1
  int (*p4)[5] = &arr;  // arr整个数组的地址
    // 数组指针
  int *p5[5];
  printf("size: %ld\n", sizeof(p5));  // 5*8=40字节
  char *str1 = "hello";
  printf("str1: %s\n", str1);
  // 字符串数组
  char *str[5] = {"hello", "world", "nihao", "hahaha", "xixixi"};
  printf("str[0]: %s\n", str[0]);
  printf("str[1]: %s\n", str[1]);
  printf("str[2]: %s\n", str[2]);
  printf("str[3]: %s\n", str[3]);
  printf("str[4]: %s\n", str[4]);
  return 0;
}


函数指针,指针函数


#include<stdio.h>
// 计算和(函数的声明)
int func_sum(int a, int b);
int *func_1(int a);
int main()
{
  // 函数调用原理:根据<函数入口地址>去执行对应函数。
  int c1 = func_sum(100, 200);
  printf("c1: %d\n", c1);
  // 函数类型:返回值 + 形参列表(函数头)
  // 函数名就是函数的入口地址。
  int (*p1)(int, int) = func_sum;
  int c2 = p1(300, 400);
  printf("c2: %d\n", c2);
    // 假设已知某个函数的入口地址为 0x000000FF
  // (一般用于硬件代码中,因为软件程序中函数的地址都是随机分配的。)
  // int (*p2)(int, int) = 0x000000FF;
  // int c3 = 0x000000FF(300, 400); // 直接调用入口地址为 0x000000FF的函数
  // printf("c3: %d\n", c3);
  int *p2 = func_1(100);
  printf("p2: %p\n", p2);
  return 0;
}
int *func_1(int a)
{
  int *p1 = &a;
  printf("p1: %p\n", p1);
  return p1;
}
// 计算和(函数的定义)
int func_sum(int a, int b)
{
  return a+b;
}


函数的传递


#include<stdio.h>
// 值传递(只是将数值100, 200传参)
void func_swap1(int a, int b);
// 地址传递(将数值本身的地址传递过去)
void func_swap2(int *a, int *b);
int main()
{
  int n1=100, n2=200;
  printf("n1:%d n2:%d\n", n1, n2);
  // func_swap1(n1, n2);  // 值传递,不能修改变量本身
  func_swap2(&n1, &n2);
  printf("n1:%d n2:%d\n", n1, n2);
  return 0;
}
// 地址传递(将数值本身的地址传递过去)
//    int *a = &n1;
//    int *b = &n2;
void func_swap2(int *a, int *b)
{
  int c;
  c = *a;
  *a = *b;
  *b = c;
  printf("func_swap: a:%d b:%d\n", *a, *b);
}
// 值传递(只是将数值100, 200传参)
//    int a = n1;
//    int b = n2;
void func_swap1(int a, int b)
{
  int c;
  c = a;
  a = b;
  b = c;
  printf("func_swap: a:%d b:%d\n", a, b);
}


1.地址偏移量概念


指针算术运算,可以跟数组形式相互转换


*(p+i) <==> p[i]


备注:


数组名不能作为等号的左值。


int a[5];
        printf("%d ", *(a++));
        printf("%d ", *(a=a+1));


  1. []的优先级是高于解引用*


  1. 对数组地址进行解引用,会得到数组的首元素地址。


  1. 数组首元素地址和数组本身地址:


int a[5] = {1, 3, 5, 7, 9};
    printf("a   : %p\n", a);    // 数组首元素地址
    printf("&a  : %p\n", &a);   // 数组本身地址
        // 上述两个地址在数值上是一样的,但是类型不相同。
    printf("a+1 : %p\n", a+1);  // 向右偏移4字节(类型:int *)
    printf("&a+1: %p\n", &a+1); // 向右偏移20字节(类型:int (*)[5])


2.数组指针、指针数组、函数指针、指针函数



  1. 数组指针:指向数组的指针。(也称为行指针,指向二维数组一行数据)


int (*p4)[5]; // 该指向指向  int [5]类型的数组


作用:一般用于二维数组访问。


  1. 指针数组:存储着一系列的相同类型指针的数组。


int *p4[5]; // 该数组存储着5个指针(类型为 int *)


(数组三要素:连续内存+具体长度+相同类型)


作用:存储多个值,指向多个数据

  1. 函数指针:指向函数类型的指针。


int (*p1)(int, int) = func_sum; // 该指针指向函数 func_sum


作用:直接通过指针调用函数。(如回调函数)


  1. 指针函数:返回值为指针的函数(返回地址)


int *func_1(int a) // 返回值为int *


如果返回值为 void *,表示返回无值型指针(任意类型指针)。


循环遍历二维数组


#include<stdio.h>
// *(p+i) <==> p[i]
int main()
{
  // int arr[2][3] = {1, 3, 5, 2, 4, 6};
  int arr[2][3] = {{1, 3, 5}, {2, 4, 6}}; //更为规范的写法
  // int *p1 等同于 int (*p1)
  // int *p1 = arr;   // 错误写法。类型不匹配。
//  int * = int (*)[3] 
//  整型指针 = 数组指针
  int *p2 = &arr[0][0]; // 类型匹配
//  int * = int *
//  整型指针 = 整型指针
  int (*p3)[3] = arr;   // 类型匹配
//  int (*)[3]   = int (*)[3]
//  数组指针      = 数组指针
// 1.通过数组名访问
  int i, j;
  for(j=0; j<2; j++)
  {
    for(i=0; i<3; i++)
      printf("%d ", arr[j][i]); 
      // printf("%d ", *(*(arr+j)+i)); 
      // printf("%d ", *(arr[j]+i)); 
      // printf("%d ", (*(arr+j))[i]); 
        // 上述四种写法效果一模一样。
      // printf("%d ", *(arr+j)[i]);  // 错误写法。因为[]优先级高于解引用*
    printf("\n");
  }
// 2.通过整型指针访问
  printf("==============================\n");
  for(i=0; i<2*3; i++)
    // printf("%d ", *p2++);
    // printf("%d ", *(p2+i));
    printf("%d ", p2[i]);
  printf("\n");
// 3.通过数组指针访问
  printf("==============================\n");
  for(j=0; j<2; j++)
  {
    for(i=0; i<3; i++)
      // printf("%d ", p3[j][i]);   // arr[j][i]
      printf("%d ", *(*(p3+j)+i)); 
      // printf("%d ", *(p3[j]+i)); 
      // printf("%d ", (*(p3+j))[i]); 
        // 上述四种写法效果一模一样。
    printf("\n");
  }
  return 0;
}


循环遍历一维数组


#include<stdio.h>
int main()
{
  int a[5] = {1, 3, 5, 7, 9};
  // int *p1 = &a[0];   // 定义指针,指向首元素a[0]
  int *p1 = a;      // 数组名就是首元素地址
//  int * = int *    类型匹配!
  printf("1: %p\n", p1);
  for(int i=0; i<5; i++)  // 0 1 2 3 4
  {
    // 写法1.1:指针本身进行偏移
    // printf("%d ", *p1);  // 对指针进行解引用
    // p1++;  //p1 = p1+1; //p1+=1;
    // 写法1.2
    // printf("%d ", *p1++);  // ++优先级更高,但是它作为后缀,必须在运算结束后再自加
    // printf("%d ", *(p1++));  // 等同于上一行
    // printf("%d ", (*p1)++);  // 错误写法。解引用后都是获得数据1。
    // 写法2:指针进行运算
    // printf("%d ", *p1+i);  // 错误写法。解引用*的优先级高于+
    // printf("%d ", *(p1+i));  // 正确写法。
    // printf("%d ", *(i+p1));  // 正确写法。
    // 写法3:指针运算(数组形式,地址偏移量)
    // printf("%d ", p1[i]);
    // printf("%d ", i[p1]);
    // printf("%d ", a[i]);
    // printf("%d ", i[a]);
    // printf("%d ", *(a+i));
    // printf("%d ", *(i+a));
    // printf("%d ", *(a++)); //错误写法:数组名不能自增自减。*(a=a+1)
  }
  printf("\n");
  int arr[2][3] = {1, 3, 5, 2, 4, 6};
  printf("2: %p\n", p1);
  return 0;
}
相关文章
|
6月前
|
机器学习/深度学习 人工智能 安全
嵌入式会越来越卷吗?
嵌入式系统,融合硬件与软件,正以前所未有的速度普及和多样化。从智能手机到医疗保健,它们无处不在,推动着技术边界不断扩展。随着AI和IoT的发展,嵌入式系统变得更智能、高效。然而,技术进步也带来了安全挑战,数据保护和系统稳定性成为重要议题。未来,嵌入式系统将在物联网中扮演关键角色,同时教育和跨领域合作将塑造其发展路径。面对挑战,我们需要创新与合作,确保其健康且持续的进步。
|
5月前
|
C语言
嵌入式程设
嵌入式程设
|
存储 Java C#
day10嵌入式(2022.1.16)
day10嵌入式(2022.1.16)
|
传感器 人工智能 安全
有什么是嵌入式不能满足的?
从20世纪60年代开始,嵌入式系统就已经开始出现,当时主要应用于航空航天、国防、工业自动化等领域
|
自然语言处理 编译器 C语言
day11嵌入式(2022.1.17)
day11嵌入式(2022.1.17)
|
C语言
嵌入式day4(2022.1.10)
嵌入式day4(2022.1.10)
|
Linux Windows
day9嵌入式(2022.1.15)
day9嵌入式(2022.1.15)