C语言----指针(一)

在计算机的内存存储器中,拥有大量的存储单元。一般情况下,存储单元是以字节为单位进行管理的。为了区别内存中的每一个字节,就需要对每一个内存单元进行编号,且每个存储单元都有一个唯一的编号,这个编号就是存储单元的地址,称为内存地址。这样,当需要存放数据时,即可在地址所标识的存储单元中存放数据。当需要读取数据时,根据内存单元的编号或地址即可找到所需的内存单元。

根据内存地址就可以准确定位到对应的内存单元,因此内存地址通常也称为指针。

对一个内存单元来说,内存单元的地址即为指针,内存单元中存放的数据就是该内存单元的内容。

指针==地址

一、指针的定义

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

取地址符 &  如:&a(得到a的地址)

int x = 10;          //整型变量存放整型值

int *p = &a;       //整型地址(指针)变量存放整型地址

int a;
int *p = &a;  //定义一个整型指针变量p存放a的地址 
*p = 100; //即a = 100; *p间接访问符,解引用

“*”所代表的意义如下:

(1)代表双目运算符里的乘法

(2)前面有数据类型(如int等),有进行定义。所指的是指针变量 

(3)前面无数据类型,间接访问,代表解引用

指针变量比普通变量多了一个解引用。使用指针时,须要解引用才能使用。

printf("%d\n",sizeof(char *));    //这里的char是所有数据类型的一个例子

output: 4

说明:只要是输出指针,所输出的字节数都为4(在32位平台时输出4,在64位平台时输出为8)  可检测平台是多少位


X86-->32位平台                 X64-->64位平台

二、指针的应用

1、求数组长度

错误求法如下:

void Show(int arr[10])//实际已经退化成指针
{
	sizeof(arr)/sizeof(arr[0]);  //==1,不能求数组的长度
}

int main()
{
	Show(arr,sizeof(arr)/sizeof(arr[0]));  //int *
	return 0;
}

求数组长度的正确求法,代码如下:

void Show(int *arr,int len)
{
	for(int i=0;i<len;i++)
	{
		printf("%d ",arr[i]);
	}
	printf("\n");
}

2、数组元素的逆置

定义一个数组 int arr[5]={1,2,3,4,5};将其中的元素按5,4,3,2,1输出。具体代码如下:

void Reverse(int *arr,int len)
{
	int tmp;
	for(int i=0;i<len/2;i++)
	{
		tmp = arr[i];  //arr[i] == *(arr+i)
		arr[i] = arr[len-1-i];
		arr[len-1-i] = tmp;
	}
}

int main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9,10};
	Reverse(arr,sizeof(arr)/sizeof(arr[0]));
	
	return 0;
}

3、将两值a、b进行交换

以下为三种错误操作代码示例

(1)error1  未建立联系

void Swap(int a,int b)          //error1
{
	int tmp = a;
	a = b;
	b = tmp;
}

int main()
{
	int a = 10;
	int b = 20;

	Swap(a,b);

	printf("%d,%d\n",a,b);

	return 0;
}

上述代码错误原因说明:子函数swap()函数中虽然将a与b进行了交换,但在主函数main()中,又对a、b进行了赋值重新定义,使子函数swap()与主函数间没有构成联系。子函数的a、b与主函数的a、b只是恰巧变量的名称相同。要想使子、主函数间建立起联系就要使用指针进行操作。后面会有介绍。

(2)error2  未解引用

void Swap(int *p1,int *p2)
{
	int tmp;   //没有解引用
	tmp = p1;
	p1 = p2;
	p2 = tmp;
}

说明:①使用指针时需要进行解引用操作,指针才会起作用;

②子函数里仅修改指针的指向,不会影响父函数。需传指针、解引用。

 这里为了帮助理解,引出了“子函数”、“父函数”两个概念。若函数A调用了函数B,则称函数A为父函数,函数B为子函数。

(3)error3  野指针的出现

void Swap(int *p1,int *p2)
{
	int *tmp; //野指针,悬挂指针
	*tmp = *p1; //由此出错,解引用出错,系统崩溃
	*p1 = *p2;
	*p2 = *tmp;
}

无法运行,系统崩溃。

野指针:野指针是指向一个已删除的对象或未申请访问受限内存区域的指针。与空指针不同,野指针无法通过简单地判断是否为 NULL避免,而只能通过养成良好的编程习惯来尽力减少。对野指针进行操作很容易造成程序错误。

成因:①指针变量未初始化;②指针释放后未置空。

避免方法:①初始化时置NULL;②释放时置NULL。

指针未初始化,取随机值,无法访问其值地址,无操作权限,程序无法识别野指针。应养成良好的编程习惯对其进行规避。

(4)正确代码如下:

//子函数的改变要能改变父函数,需传指针,解引用 
void Swap(int *p1,int *p2) 
{
	int tmp;
	tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

int main()
{
	int a = 10;
	int b = 20;

	Swap(&p1,&p2);

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值