【C语言】初学者眼中的指针

文章详细阐述了C++中的指针概念,包括字符指针、指针常量和常量指针的差异,以及指针数组和数组指针的用法。通过示例代码说明了指针如何指向字符串、常量以及数组,并解释了数组名和指针的关系以及如何通过指针操作二维数组。
摘要由CSDN通过智能技术生成

目录

一.字符指针

二.指针常量和常量指针

三.指针数组

四.数组指针


一.字符指针

字符指针char*是指针的一种类型。

int main()
{
	char str1[] = "hello.";
	char str2[] = "hello.";
	const char * str3 = "hello.";//把一个常量字符串的首字符 h 的地址存放到指针变量中
	const char * str4 = "hello.";
	if (str1 == str2)
		printf("str1 and str2 are same\n");
	else
		printf("str1 and str2 are not same\n");
 
	if (str3 == str4)
		printf("str3 and str4 are same\n");
	else
		printf("str3 and str4 are not same\n");
    /str1与str2不相同  str3与str4相同
	return 0;
}

这里str3和str4指向的是同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域,当 几个指针。指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化 不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同,str3和str4不同。 

二.指针常量和常量指针

指针常量(int*const p):指针本身是常量,就是指针里面所存储的内容(内存地址)是常量,不能改变。但是,内存地址所对应的内容是可以通过指针改变的。

常量指针(const int* p):指向常量的指针,就是指针指向的是常量,它指向的内容不能发生改变,不能通过指针来修改它指向的内容。但是,指针自身不是常量,它自身的值可以改变,从而指向另一个常量。

例:

int main()
{
    int a = 10,
    int b = 20;
    int* p1 = &a;
    *p1 = 100;//正确
    p1 = &b;//正确
 
    const int* p2 = &a;
    *p2 = 100;//错误
    p2 = &b;//正确
 
    int* const p3 = &a;
    *p3 = 100;//正确
    p3 = &b;//错误
 
    const int* const p4 = &a;
    *p4 = 100;//错误
    p4 = &b;//错误
 
    return 0;
}

是指针常量还是常量指针取决const的位置,const在 * 前就是常量指针,const在 * 后就是指针常量

知识串联:

int main()
{
 
    const int n = 5;
    int arr[n]={1,2,3,4,5}  //错误
    注意:在定义arr数组时[]内必须是常量,而在使用arr时[]内可以是变量
    const int n 是常变量,本质是变量
 
    return 0;
}

三.指针数组

指针数组是存放指针的数组,本质是数组,其中每个元素都是一个指针变量。

例如:

int* pa[10];    //整形指针的数组,存放整形指针

char *pb[4];    //一级字符指针的数组,存放一级字符指针

char **pc[5];   //二级字符指针的数组,存放二级字符指针

注意:以int* pa[10]为例,根据优先级,先看[ ],则pa是一个数组,再结合*,这个数组的元素是 int * ,共10个元素。

通过指针数组模拟二维数组:

int main()
{
	int a[5] = {1,2,3,4,5};
	int b[] = { 2,4,6,8,0};
	int c[] = { 3,5,7,9,1 };
	int* arr[3] = { a,b,c };   //不能用&数组名,取出的是整个数组的地址会报错
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			printf("%d ", *(arr[i] + j));  //等价于printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

在这个例子中,int* arr[3] = { a,b,c };  只能用数组名(首元素地址),不能用&数组名(整个数组的地址),取出的是整个数组的地址会报错

输出结果为:

知识串联:

关于数组名:数组名是数组首元素的地址,但是有2个例外:
1. sizeof (数组名)一 数组名表示整个数组,计算的是整个数组大小,单位是字节
2. &数组名一数组名表示整个数组,取出的是整个数组的地址

四.数组指针

数组指针是指向数组的指针,也是指针的一种类型。

举例:

int * 属于整型指针

char * 属于字符指针

int( *  )[n]属于数组指针,是一个指针变量。注意 * 后加指针名字,n是常量,表明它指向了含有n个int类型元素的数组。

优先级问题:

()与[ ] 优先级相同,根据结合律,就从左向右运算。
()里是*p,先定义了指针,所以p是个指针,然后后面是[ ],才是数组,即数组指针

 例:

int main()
{
	int arr[5] = { 1,2,3,4,5};
	int(*p)[5] = &arr;
	printf("%d\n%d\n", (*p)[1],*(*p+1));  //2,2
    printf("%d\n%d\n%d\n", *p, &arr,*( * p)); //*( * p)也可用**p表示
    //*p中存放着数组的地址,*p解引得到数组地址,再解引得到数组元素
	
	return 0;
}

在这个例子中,int(*p)[5] = &arr;只能用&arr(取整个数组的地址才是数组指针),不能用arr(首元素的地址),部分编译器不会报错,但是会警告,“初始化”:“int (*)[5]”与“int *”的间接级别不同。

结合指针数组和数组指针的两个例子,要明白 指针数组中的指针指向的内容 和 数组指针指向的内容的区别

输出结果:

 

通过数组指针打印二维数组中的元素:

void my_print(int(*p)[5], int a, int b)
{
	for (int i = 0; i < a; i++)
	{
		for (int j = 0; j < b; j++)
		{
			printf("%d ", *(*(p + i) + j));//等价于printf("%d ",p[i][j]);
		}
		printf("\n\n");
	}
}
int main()
{
	int arr[3][5] = { {1,2,3,4,5},{0,2,4,6,8},{1,3,5,7,9} };
	my_print(arr, 3, 5);
	return 0;
}

这个例子中指针加1,将跨过二维数组的一行。

输出结果:

区分下列指针类型:

int* parr1[5];      //存放整型指针的数组
int(*parr2)[5];     //数组指针,该指针指向一个数组,这个数组有5个元素,每个元素的类型是int
int(*parr3[10])[5]; //parr3是一个存放数组指针的数组,该数组能够存放10个数组指针,
	                //每个数组指针能够指向一个数组,每个数组有5个int类型的元素。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值