C指针简介

 

1.为什么需要指针

第一,指针的使用使得不同区域的代码可以轻易的共享内存数据。当然你也可以通过数据的复制达到相同的效果,但是这样往往效率不太好,因为诸如结构体等大型数据,占用的字节数多,复制很消耗性能。但使用指针就可以很好的避免这个问题,因为任何类型的指针占用的字节数都是一样的(根据平台不同,有4字节或者8字节或者其他可能)。

第二,指针使得一些复杂的链接性的数据结构的构建成为可能,比如链表,链式二叉树等等。

第三,有些操作必须使用指针。如操作申请的堆内存。

2.指针概念

       指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式为:

type *var_name;

每一个变量都有一个内存位置,每一个内存位置都定义了可使用连字号(&)运算符访问的地址,它表示了在内存中的一个地址。指针是程序数据在内存中的地址,而指针变量是用来保存这些地址的变量。

 

3.程序变量在内存中存储原理

       我们编写程序变量和计算机物理内存是一一对应关系,其关系如下,通常将物理内存进行映射成虚拟内存,程序员通过操纵虚拟内存来操作变量。虚拟内存是一个较大的线性表,通常说的4G内存虚拟存储器的模型,它一共有4x1024x1024x1024 个字节,那么它的虚拟地址范围就是 0 ~ 4x1024x1024x1024-1(0x00000000-0xFFFFFFF) ,每个字节8个二进制组成。

         在内存中,每个字节都有都有一个唯一的编号(好比一栋楼里面的每个房间的门牌号),在程序中使用的变量,常量,甚至数函数等数据,当他们被载入到内存中后,都有自己唯一的一个编号,这个编号就是这个数据的地址。指针就是这样形成的。

#include<stdio.h>
int main()
{
	int a;
	char s[10];
	int *p = &a;
	char *pb = s;
	printf("a 变量的地址是%p\n",&a);
	printf("a 变量的地址是%p\n", p);
	printf("s[10] 变量的地址是%p\n", &s);
	printf("s[10]变量的地址是%p\n", pb);
	return 0;
}

指针实质上存储的是内存上一个编号,也即是某变量在内存中地址,其值是一个整数,通常用16进制进行标识。

4.指针变量

      用来保存 指针(地址) 的变量,就是指针变量。如果指针变量p保存了变量 var的地址,则就说:p指向了变量var,也可以说p指向了var所在的内存块,任何类型指针变量的空间大小都是4个字节 。

5.指针的定义使用

       定义变量时,在变量名 前 写一个 * 星号,这个变量就变成了对应变量类型的指针变量。必要时要加( ) 来避免优先级的问题,比如函数指针。

#include<stdio.h>
int main()
{
	//语法:变量类型 * 指针变量名称 int* p,同时定义两个指针,则需要在每个变量前加*int *p1,*p2

	int a; //int类型变量 a
	int* p; //int* 变量p
	int arr[3]; //arr是包含3个int元素的数组
	int(*parr)[3]; //parr是一个指向【包含3个int元素的数组】的指针变量

	//-----------------各种类型的指针------------------------------

	int* p_int; //指向int类型变量的指针 

	double* p_double; //指向double类型变量的指针 

	struct Student *p_struct; //结构体类型的指针

	int(*p_func)(int, int); //指向返回类型为int,有2个int形参的函数的指针 

	int(*p_arr)[3]; //指向含有3个int元素的数组的指针 

	int** p_pointer; //指向 一个整形变量指针的指针
	return 0;
}

特殊的情况,他们并不一定需要使用&取地址:

  • 数组名的值就是这个数组的第一个元素的地址。
  • 函数名的值就是这个函数的地址。
  • 字符串字面值常量作为右值时,就是这个字符串对应的字符数组的名称,也就是这个字符串在内存中的地址。

6.解析地址(求变量的值或者赋值)

对一个指针解地址,就可以取到这个内存数据,解地址 的写法,就是在指针的前面加一个*号,然后就可以对指向的内存地址上内容进行读或写。

#include<stdio.h>
int main()
{
	
	int n = 100;
	int*p = &n;
	*p = 20;  //通过指针修改指向的内存数据
	printf("n = %d\n", *p);   //通过指针读取指向的内存数据
	printf("n= %d\n", n);
	return 0;
}

7.空指针

       在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯。赋为 NULL 值的指针被称为指针。NULL 指针是一个定义在标准库中的值为零的常量。

#include <stdio.h>

int main()
{
	int  *ptr = NULL;

	printf("ptr 的地址是 %p\n", ptr);

	return 0;
}

 8.指针注意事项

(1)指针变量赋值:指针变量不可以直接使用整数变量或者常量赋值。

#include <stdio.h>

int main()
{
	int *p = 100;	//错误,不能用常量赋值
	int i = 100;
	*p = i;				//错误:p是指针变量,i是整型变量

	return 0;
}

(2)不同类型指针变量之间不能赋值(强制转化除外)

#include <stdio.h>

int main()
{
	int i = 10;
	int *p = &i;//正确:指针类型和变量类型一致
	char *pb = p;//错误,类型不同

	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值