c指针学习笔记(一)

目录

一、关于内存那点事

1.1 存储器:存储器件

1.2 在运行程序时,操作系统将虚拟内存进行分区

二、指针的相关概念

扩展

 三、指针的定义方法

3.1 简单指针

 3.2 关于指针运算符

 3.3 扩展

3.4 指针大小

 四、指针分类

五、指针和变量的关系

指针可以存放变量的地址编号

 六、 指针和数组元素之间的关系

6.1 数组元素与指针的基本关系

6.2 数组元素的引用方法

七、指针的运算

7.1 指针可以加一个整数,

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

 7.3 两个相同类型的指针还可以做减法

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

 八、指针数组

8.1  指针和数组关系

8.2  指针数组的定义方法:

8.3 指针数组的分类

 九、指针的指针 -- 二级指针


一、关于内存那点事

1.1 存储器:存储器件

外存

         外存 = 外部存储器,长期存放数据,掉电不丢失数据

        常见的外存设备:硬盘、flash、rom、u盘、光盘、磁带

内存

        内存 = 内部存储器。暂时存放数据。掉电数据丢失

        常见的内存设备:ram、DDR

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

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

32bit 物理内存空间——0x0000 0000 - 0x ffff ffff

操作系统会在物理内存和虚拟内存之间做映射。

在32位系统下,每个进程(运行着的程序)的寻址范围是4G,0x0000 0000 - 0x ffff ffff

在写应用程序,看到的都是虚拟地址

1.2 在运行程序时,操作系统将虚拟内存进行分区

在运行程序时,操作系统会将虚拟内存进行分区:

1、堆

        在动态申请内存时,在堆里开辟内存

2、栈

        主要存放局部变量(在函数内部,或复合语句内部定义的变量)

3、静态全局区

        1):未初始化的静态全局区

                静态变量(定义的时候,前面加static修饰)、或全局变量,没有初始化的,存在此区

         2):初始化的静态全局区

                静态变量、全局变量,赋过初值,存在此区

4、代码区

        存放程序代码

5、文字常量区

        存放常量

内存以字节为单位的,可以将程序中的虚拟寻址空间,看成一个很大的 一维的字符数组

提示:本章所接触的内容,涉及到的内存都是虚拟内存,更准确来说是虚拟内存的用户空间

二、指针的相关概念

操作系统给每个存储单元分配一个编号,从0x0000 0000 - 0x ffff ffff,这个编号称为i地址,

指针就是地址

 指针变量:这个变量用来存放一个地址编码——通过地址找到地址里面的内容

在32位平台下,地址总线是32位,所以地址是32位编号,即指针变量是32位即4个字节

注意

1、无论什么类型的地址,都是存储单元的编号,在32位平台下都是4个字节

即任何类型的指针变量都是4个字节大小

2、对应类型的指针变量,只能存放对应类型变量的地址

如:整型的指针变量,只能存放整型变量的地址

扩展

        字符变量char ch; ch 占一个字节,有一个地址编号,这个编号就是ch地址

        整型变量int a; a占4个字节,占有4个字节的存储单元,有4个地址编号。

 三、指针的定义方法

3.1 简单指针

数据类型 * 指针变量名

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

在定义指针变量时 * 是用来修饰变量,说明变量p是指针变量,变量名p。

 3.2 关于指针运算符

&取地址、 *取值

&:获取一个变量的地址

* :在定义一个指针变量时,起到标识作用,标识定义的是一个指针变量

        以及其他地方表示获取一个指针变量保存的地址里面的内容

void main()
{
    //定义普通变量
	int a = 100;
	//定义指针变量
	int *p;
	
	//给指针变量 赋值
	//将a地址保存在p中 
	p = &a;
	 
	printf(" a = %d  %d\n", a, *p);
	printf(" &a = %d %d\n", &a, p);
	
}

 3.3 扩展

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

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

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

3.4 指针大小

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

而在64位系统下,所有类型的指针都是8个字节,

不管地址内的空间多大,但地址编号的长度都是一样的,所以32位操作系统中,地址都是4个字节;64位系统,地址都是8个字节


void main()
{
    char *a;
    short *b;
    int *c;
    long *d;
    float *e;
    double *f;
    
	printf(" sizeof(a) = %d \n", sizeof(a));
	printf(" sizeof(b) = %d \n", sizeof(b));
	printf(" sizeof(c) = %d \n", sizeof(c));
	printf(" sizeof(d) = %d \n", sizeof(d));
	printf(" sizeof(e) = %d \n", sizeof(e));
	printf(" sizeof(f) = %d \n", sizeof(f));
}

 

 四、指针分类

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

字符指针

字符型数据地址

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

 2 短整型指针

short int  *p;//定义一个短整型指针变量,只能存放短整型数据的地址
short int a;
p = &a;

3 整型指针

 int  *p;//定义一个整型指针变量,只能存放整型数据的地址
 int a;
 p = &a;
//注意:
/*
多字节变量,占用多个存储单元,每个存储单元都有地址编号,
c中,存储单元编号最小的那个 —— 是多字节变量的地址编号

*/

 4 长整型指针

long int  *p;//定义一个长整型指针变量,只能存放长整型数据的地址
long int a;
p = &a;

5 float型 double型指针

float  *p;//定义一个float  型指针变量,只能存放float  型数据的地址
float  a;
p = &a;


double *p;//定义一个double指针变量,只能存放double数据的地址
double a;
p = &a;

6 函数指针

7 结构体指针

8 指针的指针

9 数组指针

总结:无论什么类型的指针变量,在32位操作系统下,地址都是4个字节;64位系统,地址都是8个字节,只能存放对应类型的变量地址编号

五、指针和变量的关系

指针可以存放变量的地址编号

        在程序中,可以引用变量的方法。

1 直接通过变量的名称

int a;
a = 100;

2 可以通过指针变量来引用变量

int *p;
p = &a;
*p = 100;

注意:指针变量在定义的时候可以初始化

int a;
int *p = &a;

变量a 必须在指针调取前开辟空间。

注意:指针变量只能保存已经开辟好空间的地址,不能自己直接给随便赋地址

void main()
{
   int *p1, *p2, temp, a, b;
   p1 = &a;
   p2 = &b;
   
   printf("请输入:a b的值:\n");
   scanf("%d %d", p1, p2);
   
   temp = *p1;
   *p1 = *p2;
   *p2 = temp;
   
	printf("a = %d  b = %d\n", a, b);
	printf("*p1 = %d *p2 = %d \n", *p1, *p2);
}

扩展:

对应类型的指针,只能保存对应类型数据的地址。

如果想让不同类型的指针相互赋值时,需要强制类型转换

void *p;

void main()
{
   int a = 0x1234, b = 0x5678;
   char *p1, *p2;
   printf("a = %#x  b = %#x\n", a, b);
   
   p1 = (char *)&a;
   p2 = (char *)&b;
   
   printf("*p1 = %#x *p2 = %#x \n", *p1, *p2);
   
   p1++;
   p2++;
   printf("*p1 = %#x *p2 = %#x \n", *p1, *p2);
}

 注意:

1、* + 指针取值,取几个字节,由指针类型决定的

  • 指针为字符指针则取一个字节,
  • 指针为整型指针则取4个字节,
  • 指针为double型指针则取8个字节。

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

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

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

 六、 指针和数组元素之间的关系

6.1 数组元素与指针的基本关系

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

int a[10];
int *p;
p = &a[0];

6.2 数组元素的引用方法

  •   方法一: 数组名[下标]
int a[10];
a[2] = 100;
  •  方法二:指针名加下标
int a[10];
int *p;
p = a;
p[2] = 100;

 补充:数组名字就是数组的首地址,即第0个元素的地址,是个常量

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

例如:int a[10]; a++就是错误的,因为a是数组名是一个地址常量

  •  方法三:通过指针运算加取值方法来引用数组的元素
int a[10];
int *p;
p = a;
*(p + 2) = 100; // 相当于a[2] = 100
//p是第0个元素的地址, p +2是a[2]这个元素的地址。

void main()
{
   int a[5] = {0, 1, 2, 3, 4};
   int *p;
   p = a;
   
   //只要将数组名赋值给同类型的指针变量,则此时指针变量与数组名可以用相同方法操控数组 
   printf("a[2] = %d \n", a[2]);
   printf("p[2] = %d \n", p[2]);
   
   //*(a + n ) <==> *(p + n) <==> a[n] <==> p[n] 
   printf("*(p + 2) = %d \n",*(p + 2));
   printf("*(a + 2) = %d \n", *(a + 2));
   
   printf("p  = %p \n", p);
   printf("p + 2 = %p \n", p + 2);
   printf("&a[0] = %p \n", &a[0]);
   printf("&a[2] = %p \n", &a[2]);
}

七、指针的运算

7.1 指针可以加一个整数,

往下指几个它指向的变量,还是地址

 前提:指针指向数组时,加一个整数才有意义

void test1()
{
	int a[10];
	int *p,*q;
	
	p = a;
	q = p + 2;
	
	//p和q间隔 8个字节,意味加一个整数最终移动的字节数与指针变量的类型有关 
    printf("p  = %p \n", p);
    printf("q  = %p \n", q);
	return;
 } 
 

void main()
{
   test1();
}

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

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

指向前面元素的指针小于指向元素后面的指针

 void test2()
{
	int a[10];
	int *p,*q;
	
	p = &a[1];
	q = &a[2];
	if(p < q)
	{
		printf("p < q\n");
	}
	else if(p > q) 
	{
		printf("p > q\n");
	}
	else
	{
		printf("p = q\n");
	}
	return;
 } 

void main()
{
   test2();
}

 7.3 两个相同类型的指针还可以做减法

前提:必须是两个相同类型的指针指向同一数组的元素时,做减法才有意义

做减法的结果:两个指针指向的中间有多少个元素

void test3()
{
	int a[10];
	int *p,*q;
	
	p = &a[0];
	q = &a[3];
   
    printf("q - p  = %d \n", q - p);
	return;
 } 

void main()
{
   test3();
}

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

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

 void test4()
{
	int a = 100;
	int *p,*q;
	
	p = &a;
	printf("a = %d *p = %d \n", a, *p);
	
	q = p;
    printf("*q  = %d \n", *p);
    
    *q = 999;
    printf("a = %d  \n", a);
	return;
 } 

void main()
{
   test4();
}

 

 八、指针数组

8.1  指针和数组关系

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

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

注意:一般遇到这种叠词,本质就是后者

8.2  指针数组的定义方法:

int *p[10]; //定义一个整型的指针数组p,有10个元素p[0]-p[9],每个元素都是int *类型的变量

8.3 指针数组的分类

不同类型定义不同指针数组


void main()
{
	//大多数情况下,指针数组都用来保存多个字符串 
	char *name[5] = {"follow me", "hello", "BASIC", "FORTRAN", "BYE"};
	int i;
	
	for(i = 0; i < 5; i++)
	{
		printf("%s\n",name[i]);
	}
}

 九、指针的指针 -- 二级指针

指针的指针,即指针的地址

定义一个指针变量本身指针变量占4个字节,指针变量也有地址编号

int a;

int *p;
p = &a;
*p === a

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

int ***m;
m = &q;
*(*(*(m))) === a

 注意: 

 p q m都是指针变量,都占4个字节,都存放地址编号,只不过类型不一样。

void main()
{

	int a = 100;
	//定义一个一级指针,用于保存普通变量的地址 
	int *p = &a;
	//定义一个二级指针
	//二级指针用于保存一级指针的地址 
	int **q = &p;
	
	
	
	printf("a = %d  %d  %d\n", a, *p, **q);
	printf("&a = %p %p %p\n", &a, p, *q);
	printf("&p = %p %p\n",  &p, q);
	printf("&q = %p\n ",  &q);
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值