c语言学习二指针

 
指针的作用:
1、表示一些复杂的数据结构
2、快速传递数据(传参结构体中和函数处理数组的时候)
3、使函数返回一个以上的值
4、能直接访问硬件(因为它里面存的是硬件上的一个地址)
5、能够方便的处理字符串
6、是理解面向对象语言中引用的基础
总结;指针是c语言的灵魂 
指针的定义:

    地址:内存单元的编号(从零开始的非负整数)范围:4G【0--4G-1】

    指针:
指针与指针变量:
指针就是地址,地址就是指针
地址就是内存单元的编号
指针变量是一个变量,什么样的变量呢?一个存放地址的变量
指针与指针变量是两个不同的概念可以换一句话说(地址和地址变量)
但是注意:通常我们叙述时会把指针变量简称为指针,实际上含义是不同的
指针的本质是一个操作受限的非负整数(指针不能加、乘、除只能相减(即可以相减得出两个房间号中间隔了多少内存))
指针的分类:
    1、基本类型指针
include<stdio.h>
   //指针变量就是地址变量即能存放其他变量的地址
int main(void)
{
int* p;//p是变量的名字(p是指针变量即p能存放整形变量的地址) int*表示变量存放的是int类型变量的地址
  /*
  1、int* p 不表示定义了一个名字叫做*p的变量
  2、int* p 应该这样理解:p是变量名,p变量的类型为 int*类型(既存放int变量地址的类型)
  3、所谓int*类型  实际就是存放int变量地址的类型
 

 */
int i = 10;
p = &i;
/*

 1、p保存了i的地址,因此p指向i。
 2、p不是i,i也不是p,更准确的说修改p的值不会影响i的值,修改i的值也不会影响p的值
 3、如果一个指针变量指向了某个普通变量,则
 *指针变量    就完全等同于   普通变量

 例如:
 如果p是个指针变量,并且p存放了普通变量i的地址
 则p指向了普通变量i
 *p  就完全等同于 i
 或者说:在所有出现*p的地方都可以替换成i
 在所有出现i的地方都可以替换成*p
 *p就是以p的内容位地址的变量的值


*/
 // p = i;// error,因为类型不一致,p只能存放int类型变量的地址,不能存放int类型变量的值
 //  p=55;//error,类型不一致

}
  附录:*的含义
           1、乘法
  2、定义指针变量
     int* p;
 //定义了一个名字叫p的指针变量,int*表示 变量p的类型(即只能存整形变量的地址)
  3、指针的运算(又叫*运算)
     该运算法放在定义好的指针变量的前面
 如果p是一个已经定义好的指针变量
 则*p表示  以p的内容为地址的变量的值
如何通过被调函数修改主调函数中普通变量的值?
       1、实参必须为该普通变量的地址
2、形参必须为指针变量
3、在被调函数中通过
        *形参名 = ....
   的方式可以修改主调函数相关变量的值

例如:
#include<stdio.h>
void fun(int* p,int*q)
{
*p = 30;
*q = 40;
}
int main(void)
{
int a = 10;
int b = 20;
fun(&a,&b);
printf("a = %d  b = %d\n",a,b);

}
  
  
2、指针和数组的关系
   指针和一维数组的关系
   一维数组名
                         一维数组名是一个指针常量
                         它存放的是一维数组第一个元素的第一个字节的地址编号

   下标和指针的关系
        如果p是一个指针变量,则p[i] 永远等价于 *(p + i)
   界定一个一维数组需要几个参数【如果一个函数处理一个一维数组,则需要接受数组的哪些信息】
        1、数组名即数组元素的首地址(数组第一个元素的地址)
2、数组的长度
指针变量的运算
      指针变量不能相加、不能相乘、不能相除、只能相减
如果两个指针变量指向的是同一块连续的空间的不同的存储单元,则这两个指针变量才可以相减
一个指针变量占几个字节【一个变量的地址是用该变量的首字节的地址来表示】
   预备知识:
   sizeof(数据类型)  功能:返回值就是该数据类型所占的字节数
     例子: sizeof(int) = 4    sizeof(char) = 1 sizeof(double) = 8
sizeof(变量名)    功能:该变量所占的字节数
总结:指针变量无论它指向谁,它本身只占四个字节。
     一个变量的地址是用该变量首字节的地址来表示。

指针和二维数组的关系
3、指针和函数的关系
4、指针和结构体的关系

5、多级指针

1、指针使用的常见错误:

#include<stdio.h>
int main(void)
{
	int i = 5;
	int* p;
	int*q;
	
	p = &i;
	*q = p;//语法错误也会报错因为*q是整形变量而P是一个地址变量
	*q = *p;//语法没错,但是q没有指向里面是个垃圾地址
	p=q;
	/*
	q的空间是属于本程序的,所以本程序可以读写q中的内容,
	但是如果q内部是垃圾值,则本程序不能读写*q中的内容,
	以为此时*q所代表的内存单元的控制权限并没有(不一定)分配给本程序。
	*/

	printf("%d",*p);
	return 0;
}

指针常见错误2因为指针变量没有指向,他有可能存的地址是系统分配给本程序以外的内存。那么本程序对本程序以外的内存没有读写的权限。

#include<stdio.h>
int main(void)
{
	int *p;
	int i=5 ;

	*p = i;//会报错指针变量没有指向或里面是一个垃圾值会报错(因为p中存放的地址可能不是系统分配给本程序的内存的地址)
	printf(" %d ",*p);
	return 0;
}

这样是对的:先给指针一个指向。

#include<stdio.h>
int main(void)
{
	int *p;
	int i ;
	p = &i;
	*p = 3;
	printf(" 整形变量i的地址为: %d\n指针变量p中存放的地址为: %d\n变量i中的数值为: %d\n",&i,p,i);
	return 0;
}

2、指针的两个经典交换题

#include<stdio.h>
void Exchange(int* x,int* y);
int main(void)
{
	int a= 10;
	int b = 20;
	int *pointer1,*pointer2;
	pointer1 = &a;
	pointer2 = &b;
	Exchange(pointer1,pointer2);
	printf("a=%d  b=%d\n",a,b);
}
void Exchange(int* p1,int* p2)
{
	int z;
	z = *p1;
	*p1=*p2;
	*p2= z;
}

运行结果:


分析:


另一种:

#include<stdio.h>
void Exchange(int* x,int* y);
int main(void)
{
	int a= 10;
	int b = 20;
	Exchange(&a,&b);
	printf("a=%d  b=%d\n",a,b);
	return 0;
}
void Exchange(int* x,int* y)
{
	int*z;
	z = x;
	x=y;
	y= z;
	printf("*X = %d  *y = %d\n",*x,*y);
}

运行结果:

扫描二维码关注公众号,回复: 1985940 查看本文章


内存分析图:


3、数组名的含义:数组名是数组元素第一个元素第一个字节的地址

#include<stdio.h>
int main(void)
{
	int a[5];
	int b[5];
	//a = b;//error,a是常量
   //a = &b[3];//error a 是常量
	printf("数组名a =%#X\n第一个元素的首地址&a[0] = %#X\n",a,&a[0]);
	return 0;
}

运行结果;


4、数组和下标的关系: 如果p是一个指针变量,则p[i] 永远等价于 *(p + i)

#include<stdio.h>
int main(void)
{
	int a[5] ={1,2,3,4,5};
	int b =10;
	int *p ;
	p = &b;
	printf("======输出数组名就相当于输出一个指针变量里面存的内容即一个地址(数组名里面存的是数组数组中第一个元素的地址)======\n");
	printf("数组名    a = %#X\n数组中&a[0] = %#X\n",a,&a[0]);
	printf("====数组名就是一个指针变量里面存的是数组第一个元素的地址====\n");
	printf("     a = %#X\n &a[0] = %#X\n",a,&a[0]);
	printf(" (a+0) = %#X\n &a[0] = %#X\n",(a+0),&a[0]);
	printf(" (a+1) = %#X\n &a[1] = %#X\n",(a+1),&a[1]);
	printf(" (a+2) = %#X\n &a[2] = %#X\n",(a+2),&a[2]);
	printf(" (a+3) = %#X\n &a[3] = %#X\n",(a+3),&a[3]);
	printf(" (a+4) = %#X\n &a[4] = %#X\n",(a+4),&a[4]);
  
	printf("====利用指针输出数组中的元素=====\n");
	printf("    *a = %d\n  a[0] = %d\n",*a,a[0]);
	printf("*(a+0) = %d\n  a[0] = %d\n",*(a + 0),a[0]);
    printf("*(a+1) = %d\n  a[1] = %d\n",*(a + 1),a[1]);
    printf("*(a+2) = %d\n  a[2] = %d\n",*(a + 2),a[2]);
	printf("*(a+3) = %d\n  a[3] = %d\n",*(a + 3),a[3]);
	printf("*(a+4) = %d\n  a[4] = %d\n",*(a + 4),a[4]);
   

	return 0;
}

运行结果:


5、确定一个数组最少需要数组名和数组的长度。则p[i] 永远等价于 *(p + i)

#include<stdio.h>
void fun(int* pAry,int len)//输出数组
{
	/*
	      *(pAry + i)或pAry[i]输出数组的值
	*/

	int i;
	for( i = 0;i<len;i++)
	{
		printf("%d\n",pAry[i]);
	}
	printf("======华丽的分割线========\n");
		for( i = 0;i<len;i++)
	{
		printf("%d\n",*(pAry+i));//好好理解
	}
	printf("=====华丽的分割线======\n");
}
int main(void)
{
	int a[5] ={1,2,3,4,5};
	int b[9] = {9,8,7,6,5,4,3,2,1};
	fun(&a,5);
	fun(&b,9);
	return 0;

}

运行结果:


6、函数处理数组:最少需要数组名和数组的长度。则p[i] 永远等价于 *(p + i)

#include<stdio.h>
/*
 因为a[3]等价于*(a+3)而*(a+3)是数组的第四个元素,所以a[3]为数组的第四个元素
*/
void fun(int* pAry,int len)
{
	pAry[5] = 88;
	//*(pAry + 5) = 88;
}
int main(void)
{
	int a[6] = {1,2,3,4,5,6};
	printf("%d\n",a[5]);
	fun(a,6);
	printf("%d\n",a[5]);
	return 0;
}

运行结果:


7、指针变量的运算,只能相减,不能相加,也不能相除,

#include<stdio.h>
int main(void)
{
	int i = 5;
	int j = 10;
	float x = 10;
	float *y;
	int *p1,*q1,*p2,*q2;
	int a[5];
	p2 = &a[1];
	q2 = &a[4];

	p1 = &i;
    q1 = &j;
	y = &x;

	printf("p和q指向的单元相隔  %d  个单元没有实际意义因为不连续\n",p1-y);
	printf("p2和q2指向的单元相隔  %d  个单元\n",q2-p2);
	return 0;
}

运行结果:


8、指针变量接收地址详解

#include<stdio.h>
int main(void)
{
	char ch = 'a';
	int a = 10;
	double b = 6.66;
	char*p = &ch;
	int*q = &a;
	double*r = &b;
	printf("char*类型的指针变量所占的字节数 = %d\nint*类型的指针变量所占的字节数 = %d\ndouble*类型的指针变量所占的字节数 = %d\n",sizeof(p),sizeof(q),sizeof(r));
	printf("======华丽的分割线=======\n\n");
	printf("char类型变量所占的字节数= %d\nint类型变量所占的字节数 = %d\ndouble类型变量所占的字节数 =  %d\n",sizeof(ch),sizeof(a),sizeof(b));
    return 0;
}

运行结果:


内存分析:



猜你喜欢

转载自blog.csdn.net/boy_of_god/article/details/80951632