指针详解(二)

目录

         一、字符串指针

二,指针数组

 三、数组指针

四、 &数组名VS数组名

五、数组传参

1.一维数组传参

​ 2.二维数组传参

 3. 一级指针传参

4.二级指针传参 


  一、字符串指针

   在指针的类型中我们知道有一种指针类型为字符指针 char*,例如

 int main()
{
  char ch = 'w';
  char *pc = &ch;

 *pc = 'w';
  return 0;

}

还有一种使用方法如下

 int main()

{
    char arr[] = "abcdef";
    const char* ps = "abcdef";
    printf("%p\n", ps);//给出字符串的起始地址,打印出字符串
    return 0;
}

 看到这里,肯定会有人认为char* ps = "abcdef"放入的是一个字符串,其实并不是,这里存放的是字符串首元素的地址,也就是a的地址。

注意:常量字符串不可更改,所以前面一定要加const

二,指针数组

      指针数组,简单的理解就是存放指针的数组,例如

      

 

 三、数组指针

  数组指针是指针?还是数组?
  答案是:指针。
  我们已经熟悉:
  整形指针: int * pint; 能够指向整形数据的指针。
  浮点型指针: float * pf; 能够指向浮点型数据的指针。
  那数组指针应该是:能够指向数组的指针。

int *p1[10];
int (*p2)[10];
//p1, p2分别是什么?

    int arr[10] = { 1,2,3,4,5 };
    int (* pa)[10] = &arr;

//取出的是数组的地址存放到pa中,pa是数组指针变量
解释:p先和*结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫数组指针。

类似于int*a的指针类型是int*,float*b的类型是float*,此数组指针的类型为int(*)[10].
[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。 

 数组指针的用法:

#include<stdio.h>
void print1(int*arr,int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d", arr[i]);
	}
}
void print2(int(*p)[10],int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d", (*p)[i]);//*p取的是arr,即首元素地址
	}
}
//这种方法并不常用,多用于二维数组,如下print4
void print3(int arr[3][5], int r, int c)//r行,c列
{		 
	int i = 0;
	for (i = 0; i < r; i++)
	{
		int j = 0;
		for (j = 0; j < c; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}
void print4(int(*p)[5], int r, int c)
{
	int i = 0;
	for (i = 0; i < r; i++)
	{
		int j = 0;
		for (j = 0; j < c; j++)
		{
			printf("%d ", *(*(p + i) + j));//*(p+i)相当于第i行的地址, *(*(p + i) + j)第i行第j个元素
		}
		printf("\n");
	}
}
void test1()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	print1(arr, sz);
	print2(&arr, sz);//&arr整个数组的地址,需要用到数组指针
}
void test2()
{
	int arr[3][5] = { {1,2,3,4,5},{6,7,8,9,10}, {11,12,13,14,15} };
	print3(arr,3,5);
	print4(&arr,3,5);
}
int main()
{
	test1();
	test2();
	return 0;
}

  二维数组的首地址就是二维数组的第一行,arr 是二维数组的数组名,arr就是第一行的地址

四、 &数组名VS数组名

先来看一段代码

 可以看到,三个结果一样,第三个和前两个是有区别的,下面给它们分别+1;

 

 int arr[10] = { 1,2,3,4,5 };
    printf("%p ", arr);//数组名为首元素地址,类型为int*
    printf("%p ", arr+1);指针加一个整型,向后走4个字节
    printf("%p ", &arr[0]);//同样为首元素地址,类型为int*
    printf("%p ", &arr[0]+1);指针加一个整型,向后走4个字节
    printf("%p ",&arr);取整个元素的地址,类型为int(*)[10],就是上面提到的数组指针
    printf("%p ", &arr+1);//数组的地址+1,跳过整个数组的大小,所以 &arr+1 相对于 &arr 的差值是40.

 数组名是数组首元素的地址
 有2个例外:
 1. sizeof(数组名)
 2. &数组名

五、数组传参

1.一维数组传参

#include <stdio.h>
void test(int arr[])
{}
void test(int arr[10])
{}
void test(int *arr)
{}
void test2(int *arr[20])
{}
void test2(int **arr)
{}
int main()
{
int arr[10] = {0};
int *arr2[20] = {0};//指针数组
test(arr);//传数组名本质上为传首元素地址
test2(arr2);

}

//数组传参,形参可以是数组,也可以是指针,数组写不写大小都可以

 2.二维数组传参

void test(int arr[][5])
{}
//注意:二维数组传参,函数形参的设计只能省略第一个[]的数字。
//因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。
//这样才方便运算。

或:
void test(int (*arr)[5])
{}
int main()
{
int arr[3][5] = {0};
test(arr);
}
 

 3. 一级指针传参

#include <stdio.h>
void print(int *p, int sz)
{
int i = 0;
for(i=0; i<sz; i++)
{
printf("%d\n", *(p+i));
}
}
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9};
int *p = arr;
int sz = sizeof(arr)/sizeof(arr[0]);
//一级指针p,传给函数
print(p, sz);
return 0;
}

 当一个函数的参数部分为一级指针,能接受什么参数呢?

void test(int*p)

{}

int a=0;

int*p=&a

test(&a);

test(p);

int arr[10]={0};

test(arr)

4.二级指针传参 

#include <stdio.h>
void test(int** ptr)
{
  printf("num = %d\n", **ptr);
}
int main()
{
 int n = 10;
 int*p = &n;
 int **pp = &p;
 test(pp);
 test(&p);
 return 0;
}

 当一个函数的参数部分为一级指针,能接受什么参数呢?

 void test(int**p)

{}

int a=0;

int*p=&a;

int**pp=&p

test(&p);

test(pp);

int*arr[10];

test(arr)

  • 13
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值