C语言——指针

定义

存储内存单元地址,变量

类型名 *变量名

int i=10; //内存开辟空间 ,i地址为 012FFB90
int *p=&i;  //将i的地址存放在p变量中

 使用:

指针变量的值

        p  : 存储的地址;

       *p  :地址随对应的值;  //指针的解引用,通过解引用可以对指针所指向地址的值进行操作

 

void pointorInit()
{
	int i = 10;
	int* p = &i;

	printf("i的地址——%p\n", &i);
	printf("p的值——%p\n", p);
	printf("*p的值——%d\n", *p);  //指针的解引用
	*p = 15;
	printf("i的值——%d\n", i);
}

大小及类型

32位:4个字节

64位:8个字节

void pointorSize()
{
	char* p1 = NULL;
	int* p2 = NULL;
	float* p3 = NULL;
	double* p4 = NULL;
	printf("char类型——%d\n", sizeof(p1));
	printf("int类型——%d\n", sizeof(p2));
	printf("float类型——%d\n", sizeof(p3));
	printf("double类型——%d\n", sizeof(p4));
}

 32位

 类型意义

 指针类型决定了指针移动的距离

void pointorMove()
{

		int n = 10;
		char* pc = (char*)&n;
		int* pi = &n;

		printf("%p\n", &n);
		printf("%p\n", pc);
		printf("%p\n", pc + 1);
		printf("%p\n", pi);
		printf("%p\n", pi + 1);
		
}

 

char类型移动了1字节

int类型移动了4字节

野指针

指针指向位置不可知; 

1.指针未初始化

        默认为随机值

2.指针越界

        数组越界

#include <stdio.h>
int main()
{
    int arr[10] = {0};
    int *p = arr;
    int i = 0;
    for(i=0; i<=11; i++)
   {
        //当指针指向的范围超出数组arr的范围时,p就是野指针
        *(p++) = i;
   }
    return 0;
}

3.指针指向的空间释放

避免

1. 指针初始化

2. 小心指针越界

3. 指针指向空间释放即使置NULL

4. 指针使用之前检查有效性

指针操作

赋值

将地址赋给指针

解引用

*运算符给出指针指向地址上存储的值

不能解引用未初始化的指针

int *p;		//未初始化的指针
*p=5;		//错误

第二行的意思是把5储存在p指向的位置。

但p为被初始化,其值为一个随机值,所以5存储的位置未知。

可能不会有错,也可能会崩溃。

创建一个指针时,系统只分配了存储指针本身的内存,并未分配存储数据的内存。

在使用前一定要用已分配的地址初始化它。

还可以使用malloc()函数先分配内存

取址

指针也是变量,也有自己的地址

&运算符取出指针本身的地址

指针+-整数

指针指向地址的前移或后移,移动大小为指针类型大小与整数相乘

递增递减指针

指向数组元素的指针可以让该指针移动至数组的下一个或上一个元素

指针-指针

计算两个指针的差值,同常,求差的指针分别指向同一个数组的不同元素,差值为两元素之间的元素个数

示例

void my_strlen()     
{
	char s[] = "hellow";
	char* p = s;
	while (*p != '\0')
		p++;
	printf("%d\n",p - s);
}

比较

使用关系运算符可以比较两个指针的值,前提时两个指针指向相同类型的值

标准规定:

允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许 与指向第一个元素之前的那个内存位置的指针进行比较。

指针与数组

void pointorArray()
{
	int ar[10] = { 1,2,3,4,5,6,7,8,9,10 };
	ar[0] = 100;  //ar[0] ==> *(ar+0) ==> *(0+ar)==>0[ar]
	0[ar] = 1000;
 
	//1     数组的使用,方便人们的使用 
	for (int i = 0; i < 10; ++i)
	{
		printf("%d ", ar[i]);
	}
	printf("\n");
 
	//2     数组的底层实现
	for (int i = 0; i < 10; ++i)
	{
		printf("%d ", *(ar + i));
	}
	printf("\n");
 
	//3     指针变量获取数组首地址,指针操作数组 
	int* p = ar;
	for (int i = 0; i < 10; ++i)
	{
		printf("%d ", *(p + i));
	}
	printf("\n");
 
	//4     2、4 等价
	int* q = ar;
	for (int i = 0; i < 10; ++i)
	{
		printf("%d ", q[i]);
	}
	printf("\n");
 
}

标准规定:

         允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许 与指向第一个元素之前的那个内存位置的指针进行比较。

 

二级指针

还是指针

存储指针的指针  

类型名**指针名

void secondPointor()
{
	int i = 10;
	int* p = &i;
	int** pp = &p;
	printf("i的地址——%p\n", &i);
	printf("p的值——%p\n", p);
	printf("p的地址——%p\n", &p);
	printf("pp的值——%p\n", pp);
	printf("*p的值——%d\n", *p);
	printf("*pp的值——%p\n", *pp);
	printf("**pp的值——%d\n", **pp);
}

 

二级指针

存储指针地址的指针

类型名**指针名;

void secondPointor()
{
	int i = 10;
	int* p = &i;
	int** pp = &p;
 
	printf("i的地址——%p\n", &i);
	printf("p的值——%p\n", p);              //&i
	printf("*p的值——%d\n", *p);            //i
 
	printf("p的地址——%p\n", &p);
   printf("pp的值——%p\n", pp);	      //&p
	printf("*pp的值——%p\n", *pp);	      //&i
	printf("**pp的值——%d\n", **pp);       //i
}

 

指针数组

是数组

类型名*指针名[const]

各个元素都为指针

 void类型   可以定义指针,不可以定义变量

泛型指针不能进行任何操作,通过强转类型可以操作。

void voidPointor()       
{
	//泛型指针 void只能定义指针,且无法进行指针操作,通过强转类型可实现操作
	char ch = 'A';
	void* p1 = &ch;  //4
	printf("%c\n", *(char*)p1);

	int i = 1;
	void* p2 = &i;
	printf("%d\n", *(int*)p2);

	double d = 12.34;
	void* p3 = &d;
	printf("%f\n", *(double*)p3);
}

const修饰的指针

const int *p;

int const*p;

指针指向的地址的值不可改变;

const修饰的数组,只能用const修饰的指针指向

int*const p;

指针指向的地址不可改变;

const int *const p;

指针指向的地址的值不可改变和指向的地址不可改变;

最难不过坚持!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值