指针知识详解1

指针:指针地址或指针变量
指针的意义:
1.指针类型决定了:(1)指针解引用的权限有多大(能操作多少数);(2)指针+1或-1的步长为多少

#include <stdio.h>
int main()
{
	int* p;
	int a[5] = { 1,2,3,4,5 };
	char* p1;
	p1 = a;
	p = a;
	printf("%p\n", p);
	printf("%p\n", p + 1);
	printf("%p\n", p1);
	printf("%p\n", p1 + 1);
	return 0;
}

结果如下:

00AFF718
00AFF71C
00AFF718
00AFF719

2.野指针
指针指向的地址随机,不确定
形成原因:(1)指针为初始化(默认为随机值);

int *p;
*p=10;//非法访问内存,运行提示出错

(2)指针越界;(导致程序崩溃,无法运行)

int a[5] = { 1,2,3,4,5 };
int* p;
int i;
p = a;
	for (i = 0;i <= 5;i++)//指针越界
	{
		*p = i;
		p++;
	}

(3)指针指向的空间释放;

int * text()
{
	int a = 10;
	return &a;
}
int main()
{
	int* p = text();
	*p = 20;
	return 0;
}

其中text函数中的a作为局部变量离开被调函数就被释放。

如何规避使用野指针:
(1)指针初始化
(2)小心指针越界
(3)指针指向空间释放就置NULL

int *p=NULL;//实际上就是0;表示指针未指向任何存储空间

(4)指针使用前检验有效性

if(p!=NULL)
*p=10;

二、指针的运算
1.指针±整数

int a[3]={1,2,3};
int *p=a;
p++;
p--;

2.指针-指针(得出结果为指针与指针之间的元素个数)

int a[5] = { 1,2,3,4,5 };
	printf("%d\n", &a[4] - &a[0]);

两个指针需要在同一内存空间进行;
模拟strlen函数:

int strlen(char* st)
{
	char* p = st;
	while (*st != '\0')
	{
		st++;
	}
	return st - p;
}
int main()
{
	char a[] = "abc";
	char* str = a;
	printf("%d", strlen(a));
	return 0;
}

3.指针的关系运算

int a[5] = { 1,2,3,4,5 };
	char* p = a;
	for (;p < &a[5];p++)
	{
		*p = 0;
	}

指针与数组

int a[5] = { 1,2,3,4,5 };
	int *p = a;
	/*for (;p < &a[5];p++)
	{
		*p = 0;
	}*/
	printf("%d\n", a[2]);//3
	printf("%d\n", p[2]);//3
	printf("%d\n", *(a+2));//3
	printf("%d\n", *(p+2));//3
	printf("%d\n", 2[a]);//3
	printf("%d\n", 2[p]);//3
	printf("%d\n", *(2+p));//3
	printf("%d\n",*(2+a));//3

以上输出均等价。
2.指针数组
存放指针的数组

int *a[5];
int main()
{
	char s[] = "hello bit";
	char s1[] = "hello bit";
	const char *s2 = "hello bit";
	const char *s3= "hello bit";//s1和s2一样,内存中只会存一份
	if (s == s1)
		printf("smae\n");
	else
		printf("not same\n");
	if (s3 == s2)
		printf("smae\n");
	else
		printf("not same\n");
}

整形指针的数组:

int *a[5];

一级字符指针的数组:

char *a1[2];

二级字符指针的数组:

char **a2[2];

有点像二维数组.

int a[5] = { 1,2,3,4,5 };
	int b[] = { 2,3,4,5,6 };
	int c[] = { 3,4,5,6,7 };
	int* p[3] = { a,b,c };
	int i = 0;
	for (i = 0;i < 3;i++)
	{
		int j = 0;
		for (j = 0;j < 5;j++)
		{
			printf("%d ", p[i][j]);//printf("%d",*(*(p+i)+j));
		}
	}
	printf("\n");
int arr[5]={1,2,3,4,5};
int (*parr)[5]=&arr//取出的是数组的地址,parr是一个数组指针
arr//数组名是首元素arr[0]的地址

数组名是数组首元素的地址
除了(1)sizeof(数组名)————此处数组名表示整个数组,计算的是整个数组大小,单位是字节;(2)&数组名————此处数组名表示整个数组,取出的是整个数组的地址。

void print(int a[3][4], int b, int c)
{
	int i = 0, j = 0;
	for (i = 0;i < b;i++)
	{
		for (j = 0;j < c;j++)
		{
			printf("%d ", a[i][j]);
		}
		printf("\n");
	}
}
void print1(int(*p)[], int b, int c)
{
	int i = 0;
	int j = 0;
	for (i = 0;i < b;i++)
	{
		for (j = 0;j < c;j++)
		{
			printf("%d ", *((*p + i) + j));
		}
		printf("\n");
	}
}
int main()
{
	int a[3][4] = { {1,2,3,4},{2,3,4,5},{3,4,5,6} };
	print(a, 3, 4);
	print1(a, 3, 4);
}

细分:

int (*parr)[10];

表示:数组指针,该指针能够指向一个数组,数组10个元素,每个元素都是int型

int (*parr[10])[5];

表示:parr是一个存储数组指针的数组,该数组能够存放10个数组指针,每个数组指针能够指向一个数组,数组5个元素,每个元素都是int型。
三、数组传参,指针传参

int main()
{
	int a[10] = { 1 };
	int* a1[5] = { 2 };
	test1(a);
	test2(a1);
}

1.一维传参方式:

void test1(int a[])
{

}
void test1(int a[10])
{

}
void test1(int *a)
{

}
void test2(int *a[5])
{

}
void test2(int **a)
{

}

2.二维数组传参的三种:

void test(int a[2][3]) 
{

}
void test(int a[][3]) 
{

}
void test(int (*a)[3]) 
{

}

总结:二维数组传参,函数形参的设计只能省略第一个[]的数字,因为对于一个二维数组,可以不知道有多少行,但必须知道一行有多少元素。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值