栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言指针

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言指针

文章目录
  • 一、指针的概念
    • 1. 分清指针和指针变量
    • 2. 普通变量在内存中的存储
  • 二、定义指针变量
    • 1. 简单的指针变量的定义方式
    • 2. 操作指针的运算符
    • 3. 分清*&p和&*p
  • 三、指针的分类
    • 1. 字符型、整型、浮点型指针
    • 2. 函数、结构体、数组指针
    • 3. 多重指针和通用指针
  • 四、指针的运算
    • 1. 指针加上一个整数
    • 2. 相同类型指针比较大小
    • 3. 相同类型指针相减
    • 4. 相同类型指针相互赋值

一、指针的概念 1. 分清指针和指针变量

   在计算机中,系统会给虚拟内存中的每一个存储单元编号,每一个地址编号对应着一个字节的存储单元,这个地址编号就是指针。
  指针变量是存放某个地址编号的一个变量。在32位平台下,地址总线是32位的,所有地址编号都是32位的。指针变量不管存放什么类型的数据,这一类型的数据可能占1个字节或多个字节,但指针变量存放的都是这个数据对应的地址的第一个地址编号(如下图2),所以任何类型的指针变量都只占4个字节。

2. 普通变量在内存中的存储

  那么普通的变量(非指针变量)在内存中占几个字节呢 ?

	// 定义一个字符型变量 ch
	char ch = 'a';

	// 定义两个整型变量 num1,num2
	int num1 = 305419896;
	int num2 = 4294967295;

   定义一个字符型变量ch并赋初值值’a’,由于字符型数据在内存中储存的是它的ASCII码值,'a’的ASCII码值为97,十六进制表示为0x61,二进制表示为0110 0001,占1个字节;
   再定义一个整型变量num1的值为305419896,十六进制表示为0x12345678,二进制表示为0001 0010 0011 0100 0101 0110 0111 1000,一共32位,占4个字节;
   另一个整型变量num2的值为4294967295,十六进制表示为0xffffffff,二进制表示为1111 1111 1111 1111 1111 1111 1111 1111,一共32位,占4个字节。

图1. 普通变量在内存中的存储

十六进制带前缀输出变量ch、num1和num2的地址为:

0x2008
0x2004
0x2000

   为什么整型变量明明占4个字节,输出的地址却只有1个字节的地址?那是因为在计算机中,占多个字节的变量在内存中占多个存储单元,存储单元地址编号最小的那个编号就是这个变量的地址。
   综上,在32位平台下,内存地址、指针、指针变量都是4个字节的。

二、定义指针变量 1. 简单的指针变量的定义方式

  数据类型 * 指针变量名;

	// 定义一个整型的指针变量 p
	int * p;
2. 操作指针的运算符

  & 是取地址运算符,就是取值对应的地址,想象在一个盒子中存放着数据value,&value就是取地址,即获得这个盒子编号的操作。
  *(地址) 是取值运算符,是解引用操作符,就是取地址对应的值,可以想象成通过盒子的编号打开盒子取出数据value的操作。

	int num = 0x12345678;
	int * p; // 定义指针变量时,* 表示修饰 p 是一个指针变量
	p = #
	int a;
	a = *p;
	printf("num的地址为:%#xn",&num); // 输出 num 的地址
	printf("p存储的值为:%#xn",p); // 输出 p 存储的值
	printf("a的值为:%#x",a); // 输出 a 的值

  代码分析:定义整型变量num,假设num的地址为0x0062fe1c,给num赋初值0x12345678,指针变量p存放了num的地址,也可以说是p指向了num,p的值为0x0062fe1c。定义整型变量a,a=*p等同于a=*(&num),就相当于把num的值间接赋给了a。
十六进制带前缀输出结果为:

num的地址为:0x62fe1c
p的值为:0x62fe1c
a的值为:0x62fe1c

图2. 指针变量p存放num的首地址
3. 分清*&p和&*p

  根据C语言的运算优先级,*和&处在同一优先级,结合方式从右到左,所以*&p 等价于*(&p),&*p 等价于&(*p)。

  (1) int * p; 那么*&p 等同于 p,&*p 等同于 p,最后都是 p,只是没定义p指向哪。

  (2) int p; 那么*&p 等同于 p;而 &*p 是非法的,因为 *p 非法。例如,int p =10; 那么 *&p 等同于 *(&p) 等同于 p,最后 p 的值为10(即从p的地址取值),而 &*p 则是非法的,因为p=10,*10表示取内存地址为10的值,在c语言中是非法操作。

三、指针的分类

指针的类型按照指针指向的数据类型可以简单分为以下几类:

1. 字符型、整型、浮点型指针

(1) 字符指针

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

(2) 短整型指针

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

(3) 整型指针

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

(4) 长整型指针

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

(5) 单精度浮点型指针

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

(6) 双精度浮点型指针

	double * p; // 定义一个double 型指针变量,只能存放double 型变量的地址
	double val;
	p = &val;
2. 函数、结构体、数组指针

(1) 函数指针

	int func(int x); // 定义一个函数
	int (*p)(int x); // 定义一个函数指针变量
	p = func; // 将函数的首地址赋值给 p

(2) 结构体指针

	// 定义学生基本信息结构体
	struct student{
		char * name; // 姓名
		int sno; // 学号
		int age; // 年龄
	}
	struct student stu1; // 定义一个学生基本信息结构体变量stu1
	struct student *p = NULL; // 定义一个指向struct student类型的指针变量 p
	p = &stu1; // p 指向结构体变量stu1的首地址
	strcpy((*p).name,"张三");
	(*p).sno = 2020001;
	(*p).age= 20;

(3) 数组指针

	int a[10]; // 定义一个长度为10的整型数组
	int * p; // 定义一个整型指针变量
	p = a; // 将数组首地址赋值给 p,数组名就是数组的首地址,a是地址值,不是一个变量,p和a含义不同
	p[1] = 10; // 用指针变量 p来访问数组元素,相当于a[1] = 10
	*(p+1) = 10; // 相当于a[1] = 10
3. 多重指针和通用指针

(1) 指针的指针(多重指针)
  指针的指针就是指针的地址,定义一个指针变量,指针变量也有其地址编号。

	int num = 0x12345678;
	int * p;
	p = #
	int **q; // 定义二重指针
	q = &p; //p存放了q的地址
	int ***r; // 定义三重指针
	r = &q; // r存放q的地址

(2) 通用指针
  任何类型的指针都可以赋值给void类型的指针,而void类型的指针赋值给其它类型的指针需要进行转换。

	void * p; // 定义void类型指针变量
	int * q;
	p = q;
	int * r = (int *)p;

  在32位系统下,任何类型的指针变量都只占4个字节,指针只能存放对应类型的变量的地址编号。

四、指针的运算 1. 指针加上一个整数

  指针变量加上一个整数,结果仍是一个地址。

	int a[10];
	int * p;
	p = a;
	p = p + 1;
	printf("%#xn",a);
	printf("%#x",p);

  假设a的首地址为0x0062fe10,最终程序编译运行后输出a的值为0x62fe10,p的值为0x62fe14,p加上的1是整型数组a的一个元素的字节(4字节)。

	char b[10];
	char * q;
	q = b;
	q = q + 1;
	printf("%#xn",b);
	printf("%#x",q);

  假设b的首地址为0x0062fef0,最终程序编译运行后输出b的值为0x62fef0,q的值为0x62fef1,q加上的1是字符型数组b的一个元素的字节(1字节)。

2. 相同类型指针比较大小

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

	int a[10];
	int * p, * q;
	p = &a[1];
	q = &a[5];
	if(p > q){
		printf("p>q");
	}
	else{
		printf("p 

  输出结果为p 3. 相同类型指针相减

  相同类型的指针指向同一个数组中的元素时,相减才有意义。

	int a[10];
	int * p, * q;
	p = &a[1];
	q = &a[5];
	printf("%d",q-p);

  输出结果为4,q和p相减得到的是a[1]到a[5]之间的元素个数。

4. 相同类型指针相互赋值

  相同类型的指针(除void类型指针)之间才可以相互赋值。

	int * p;
	int * q;
	int num;
	p = #
	q = p;

  不同类型的指针要想相互赋值,必须先进行强制类型转换成相同类型的指针。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/873443.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号