嵌入式c语言指针与函数学习记录

本文详细解析了C语言中的内存结构(包括物理内存和虚拟内存)、指针概念、定义方法、分类,以及指针与数组、函数的关系,特别强调了地址传参、特殊指针如NULL和void*的应用,最后提到了main函数的参数处理。
摘要由CSDN通过智能技术生成

1、内存

存储器:

        外存:外存又叫外部存储器,长期存放数据,掉电不丢失数据。常见的外存设备:硬盘,flash,rom,u盘,光盘,磁带。

        内存:内存又叫内部存储器,暂时存放数据,掉电数据丢失。常见的内存设备:ram,DDR。

        物理内存:实实在在的存储设备。

        虚拟内存:操作系统虚拟出来的内存。当一个进程被创建的时候,或者程序运行的时候都会分配虚拟内存,虚拟内存和物理内存之间存在映射关系。

        在运行程序的时候,操作系统会将虚拟内存进行分区:1、堆:在动态申请内存的时候,在堆里开辟内存。2、栈:主要存放局部变量(在函数内部,或复合语句内部定义的变量)。3、静态全局区:1)、未初始化的静态全局区:静态变量(定义的时候,前面加static修饰),或全局变量,没有初始化的,存在此区。2)、初始化的静态全局区:全局变量、静态变量、赋过初值的,存放在此区。4、代码区:存放程序代码。5、文字常量区:存放常量的。

2、指针的相关概念

        操作系统给每个存储单元分配了一个编号,从0x00000000-0xffffffff。这个编号称之为地址,指针就是地址。

        注意:1、无论什么类型的地址,都是存储单元的编号,在32位平台下都是4个字节,即任何类型的指针变量都是4个字节的大小。

        2、对应类型的指针变量,只能存放对应类型的变量的地址。举例:整型的指针变量只能存放整型变量的地址。

3、指针的定义方法

3.1、简单的指针

        数据类型 *  指针变量名;

        int *  p; //定义了一个指针变量p

        在定义指针变量的时候,*是用来修饰当前定义的变量是一个指针变量。变量名是p。

3.2、关于指针的运算符

        & 取地址、 * 取值

        如果在一行中定义了多个指针变量,每个指针变量前面都要加*来修饰。

        int *p,*q;//定义了两个整型的指针变量p和q

        int *p,q;//定义了一个整型指针变量p和整型变量q。

        注意:在定义时,如果指针变量是个局部变量,且没有赋初值的话,它的值就是随机的,这个指针变量就是一个野指针。

3.3、指针大小

        在32位的系统下,所有类型的指针都是4个字节。

4、指针的分类

        按指针指向的数据类型来区分

4.1、字符指针

        字符型数据的地址:char *p;//定义了一个字符指针变量,只能存放字符型数据的地址编号。

4.2、短整型指针

        short int *p;//定义了一个短整型的指针变量p,只能存放短整型变量的地址。

4.3、整型指针

        int *p;//定义了一个整型的指针变量p,只能存放整型变量的地址。

还有:长整型指针、float型指针、double型指针、函数指针、结构体指针、指针的指针、数组指针

无论什么类型的指针变量,在32位系统下,都是4个字节,只能存放对应类型的变量的地址编号。

5、指针和变量的关系

        对应类型的指针只能保存对应类型数据的地址,如果想让不同类型的指针相互赋值的时候,需要强制类型转换。

        注意:1、*+指针        取值,取几个字节,由指针类型决定的指针为字符指针则取一个字节,指针为整型指针则取4个字节,指针为double型指针则取8个字节。

                2、指针++        指向下个对应类型的数据。

                        字符指针++,指向下个字符数据,指针存放的地址编号加1.

                        整型指针++,指向下个整型数据,指针存放的地址编号加4。

6、指针与数组元素之间的关系

        1、变量存放在内存中,有地址编号,咱们定义的数组,是多个相同类型的变量的集合,每个变量都占内存空间,都有地址编号,指针变量当然可以存放数组元素的地址。

        2、数组元素的引用方法

        方法1:数组名[下标]

                int a[10];

                a[2]=100;

        方法2:指针名加下标

                int a[10];

                int *p;

                p=a;

                p[2]=100;//因为p和a等价

        补充:c语言规定:数组的名字就是数组的首地址,即第0个元素的地址,是个常量。

        注意:p和a的不同,p是指针变量,而a是个常量。所以可以用等号给p赋值但不能给a赋值。

        方法3:通过指针运算加取值的方法来引用数组的元素

        int a[10];

        int *p;

        p=a;

        *(p+2)=100;//相当于a[2]=100;

7、指针的运算

        1、指针可以加一个整数,往下指几个它指向的变量,结果还是个地址。前提:指针指向数组的时候,加一个整数才有意义。

        2、两个相同类型的指针可以比较大小

          前提:只有两个相同类型的指针指向同一个数组的元素的时候,比较大小才有意义。指向前面元素的指针小于指向后面元素的指针。

        3、两个相同类型的指针可以做减法

          前提:必须是两个相同类型的指针指向同一个数组的元素的时候,做减法才有意义。做减法的结果是,两个指针指向的中间有多少个元素。

        4、两个相同类型的指针可以相互赋值

          注意:只有相同类型的指针才可以相互赋值(void *类型的除外)

          int *p;

          int *q;        

          int a;

          p = &a;//p保存a的地址,p指向了变量a

          q = p;//用p给q赋值,q也保存了a的地址,指向a

        注意:如果类型不相同的指针要想相互赋值,必须进行强制类型转换。

8、指针数组

 1、指针和数组的关系:1、指针可以保存数组元素的地址。2、可以定义一个数组,数组中有若干个相同类型指针变量,这个数组被称为指针数组。

 指针数组的概念:指针数组本身是个数组,是个指针数组,是若干个相同类型的指针变量构成的集合。

2、指针数组的定义方法:类型说明符 * 数组名[元素个数];

        int *p[10];//定义了一个整型的指针数组p,有10个元素p[0]-p[9];

        每个元素都是int *类型的变量

        int a;

        p[1]=&a;

        int b[10];

        p[2]=&b[3];

        p[2]和*(p+2)是等价的,都是指针数组中的第二个元素

3、指针数组的分类:字符指针数组char *p[10];、短整型指针数组、整型的指针数组、长整型指针数组、float型的指针数组、double型的指针数组、结构体指针数组、函数指针数组。

9、指针的指针——二级指针

        即指针的地址。

        int a;

        int *p = &a;

        int **q = &p;//*q=p   **q=*p=a

10、字符串和指针

        字符串的概念:字符串就是以'\0'结尾的若干个字符的集合。

        字符串的存储形式:数组、字符串指针、堆。

        字符数组:在内存(栈、静态全局区)中开辟了一段空间存放字符串。

        字符串指针:在文字常量区开辟了一段空间存放字符串,将字符串的首地址赋给str

        :使用malloc函数在堆区申请空间,将字符串拷贝到堆区

        1、char string[100]="I love c":定义了一个字符数组string,用来存放多个字符,并且用“I love c”给string数组初始化,字符串“I love c”存放在string中。

        2、char *str = “I love c”:定义了一个指针变量str,只能存放字符地址编号,所以说I love c这个字符串中的字符不能存放在str指针变量中。str只是存放了字符I的地址编号,“I love c”存放在文字常量区。

        3、char *str = (char*)malloc(10*sizeof*(char));//动态申请了10个字节的存储空间,首地址给str赋值。    strcpy(str,"I love c");//将字符串“I love c”拷贝到str指向的内存里。

11、数组指针

1、二维数组:二维数组a中,a+1指向下一个元素,即下一个一维数组,即下一行。

2、数组指针的概念:本身是一个指针,指向一个数组,加1跳一个数组,即指向下一个数组。数组指针的作用就是可以保存二维数组的首地址。

3、数组指针的定义方法:指向的数组的类型(*指针变量名)[指向的数组的元素的个数]。

        int (*p)[5];//定义了一个数组指针变量p,p指向的是整型的有5个元素的数组。p+1往下指5个整型,跳过一个有5个整型元素的数组。

4、数组名字取地址:变成数组指针。一维数组名字取地址,变成一维数组指针,即加1跳一个一维数组。int a[10];

        a+1跳一个整型元素,是a[1]的地址。

        a和a+1相差一个元素,4个字节

        &a就变成了一个一维数组指针,是int(*p)[10]的类型

        (&a)+1和&a相差一个数组即10个元素即40个字节

5、多维数组中指针的转换:在二维数组中,行地址取*不是取值的意思,而是指针降级的意思,由行地址(数组指针)变成这一行第0个元素的地址。取*前后还是指向同一个地方,但是指针的类型不一样了。

12、指针和函数的关系

1、指针作为函数的参数,可以给一个函数传一个整型、字符型、浮点型的数据,也可以给函数传一个地址。

        函数的传参方式:复制传参、地址传参

2、地址传参:

3、传数组:给函数传地址的时候没法一下将数组的内容作为整体传进去,只能传数组的地址。

        传一维数组:void fun1(int *p)

        传二维数组:void fun2(int (*p)[4])

        传指针数组:void fun3(char **q)

13、指针函数

        指针函数:指针作为函数的返回值。一个函数可以返回整型数据、字符数据、浮点型的数据,也可以返回一个指针。

        

14、函数指针

        函数指针:指针保存函数的地址。定义的函数在运行程序的时候,会将函数的指令加载到内存的代码段。所以函数也有起始地址。c语言规定:函数的名字就是函数的首地址,即函数的入口地址,就可以定义一个指针变量,来存放函数的地址。这个指针变量就是函数指针变量。

1、函数指针变量的定义方法:返回值类型 (*函数指针变量名)(形参列表);

        int (*p)(int,int);//定义了一个函数指针变量p,p指向的函数必须要有一个整型的返回值,有两个整型参数。

        int max(int x,int y){}

        int min (int x,int y){}

        可以用这个p存放这类函数的地址。p=max,p=min.

2、调用函数的方法:通过函数指针变量去调用。

15、特殊指针

 1、空类型指针(void *):void*:表示通用指针,任何类型的指针都可以给void*类型的指针变量赋值。 int *p; void *q; q=p;是允许的。不用强制类型转换。主要用在函数的参数和返回值的位置。

2、NULL空指针:char *p = NULL;可以认为p哪里都不指向,也可以认为p指向内存编号为0的存储单元。在p的四个字节中,存放的是0x00000000.  一般NULL用在给指针的初始化。

16、main函数传参

int main(int argc, char *argv[])

argc:是一个int类型的变量,表示命令终端传入的参数的个数

argv:是一个指针数组,用于保存每一个命令终端传入的参数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值