第七天——指针和二维数组

打印数组元素值的方式:(一维数组)
arr[i]
*(arr+i)
*(arr++) //error
i[arr]
*(p+i)
*(p++)
p[i]


***1,指针和二维数组:***

总结:对于int arr[2][3]的数组来说,arr[0][0]的类型是int ,arr[0]的类型是int *(因为arr[0] == &arr[0][0])
又因为arr == &arr[0] ,为什么arr不是int **?
(1)因为arr+1移动了12个字节(一维数组的的大小),如果是int **,应该加一移动4个字节,明显不符合。
(2)arr[0]是一维数组的数组名,能够代表整个数组,如果将数组名取址赋值个一个指针变量,相当于该指针指向了整个数组,而不是首元素。
因此:对于arr来说,arr的类型是一个指向一维数组的指针,即数组指针
在这里插入图片描述


2,数组指针:指向一维数组的指针。
本质:指针
格式:
存储类型 数据类型 (指针变量名) [元素个数];
注意:[]的优先级比
要高,所以变量名会首先和[]结合表示的是数组名,而不是指针变量名。
所以需要提高*的优先级,故加()。
分析
存储类型:该数组指针自身的存储位置
数据类型: 所指向一维数组的元素类型
该指针所指向的类型:数据类型 [元素个数]
该指针自己的类型:数据类型 ( * ) [元素个数]

int arr[5];
//定义一个数组指针指向该一维数组
int (*p)[5] = &arr;

指针的本质:
用来操作一片连续的空间才有意义。

int arr[3][4];
//定义一个数组指针
int (*p)[4] = &arr[0];
int (*p)[4] = arr;

在这里插入图片描述

在这里插入图片描述

3,指针数组:数组元素类型为指针类型
本质:数组

格式:
存储类型 数组类型 * 数组名[元素个数]

int a,c,b;

定义一个指针数组用来存储三个变量的地址
int * p[3] = {&a,&b,&c};

访问:
int  i;
for(i=0;i<3;i++)
{
	printf("%d",*p[i]);
	printf("%d",*(*(p+i)));
}

定义一个指针数组,用来存储二维数组中的每一个小一维?
int arr[3][4];

int *p[3] = {NULL};

for(i=0;i<3;i++)
{
p[i] = arr[i];
}

*(p[i] + j)
((p+i)+j)


char str[100] = {“wangjia”};//在栈区开辟了100个字节的空间,用来完全存储"wangjia"每一个字符

str[0] = ‘j’;//OK

char *str = “wangjia”; //在栈区开辟了4个字节的空间,只能存储&‘w’
注意:此时通过p去操作还是操作的是原空间
*str = ‘k’; //error

char *pstr[5] = {“wangjia”,“haha”,“xixi”,“gaga”,“hehe”};

4,const修饰的指针:
const :被const修饰的变量表示只读

int a = 90;
conat int a = 89;

总结:
(1)对于const来说,修饰完之后的变量的存储位置不会发生改变(依赖于之前的存储位置),只不过被常量化了
(2)const 没有修饰谁,谁就可以更改,const修饰谁,谁就不能被更改。

分为两类:
(1)指向常量的指针:
int a;
int *p = &a:
int const p = &a;
const int p = &a;//代表p不能被更改但是p的指向以及通过a去修改a的值都是可行的
(2)指针常量:
int * const p = &a; //代表指针的指向不能被更改,但是可以通过给
p 以及给a去赋值引起a值的改变

(3)双重修饰:const int * const p = &a;//代表*p和p的指向均不可发生改变。
int const * const p = &a;


1,拆分一个带有空格的字符串,将拆分之后的字符串保存在字符指针数组中
eg:
char str[100] = {“hello world wangjia”};
升级版:char str[00] = {" wang jia jia hh"};
在这里插入图片描述

#include <stdio.h>

#define N 100
int main(int argc, const char *argv[])
{
	//定义一个字符串
	char str[N] = {'\0'};
	//定义一个指针指向该数组的首元素
	char *p = str;
	printf("请输入一个需要分割的字符串:\n");
	gets(p);

	//定义一个字符指针数组用来存储分割之后的字符串的地址
	char *pStr[10] = {NULL};

	int count = 0;
	//遍历p所指向的数组
	while(*p)
	{
		//判断该位是否为空格
		while(' ' == *p)
		{
			p++;
		}

		//将该位保存再指针数组的第一个元素中
		if('\0' != *p)
		{
			pStr[count++] = p;
		}
		else
		{
			break;
		}
		p++;
		//判断该位不是空格,如果不是,则往后移动
		while(' ' != *p)
		{
			p++;
		}
		//当遇到第一个空格时,将空格用'\0'代替
		*p = '\0';
		p++;
	}

	printf("拆分之后的字符串为以下:\n");
	int j;
	for(j=0;j<count;j++)
	{
		puts(pStr[j]);
	}
	return 0;
}

你需要《C程序设计语言》。数组名和数组指针是不一样的。当编译器看到int arr[3][3]; 时,会给拨9个int类型大小的内存空间,而arr这个数组名则是这段内存开头处的地址。这是一个特殊的常量,不占内存空间,在编译时就知道。在代码中可以表示这个数组,也可以表示这个数组开头处的地址。编译器在看到arr[1]时,会给你改成*(arr + 1) 。然后编译器先看到arr + 1,它认为arr能与整数相加减,所以是一个地址型常量,然后算出arr + 1的值,常量加常量还是常量,这是一个典型的常量表达式,结果还是在编译时就知道。然后编译器看到了*,然后就认为你要取这个常量地址所指向的内存区域的值,然后程序正常进行。编译器又看到了&arr。这时,由于arr的值并没有内存空间,所以编译器认为你这里的arr是表示数组。所以就取到了这个数组的地址。然后程序继续运行,编译器看到了&(arr + 1); 由于优先级,它先处理arr + 1,编译器认为arr能与整数相加减,所以代表指针常量。然后计算arr + 1得到一个常量结果,然后编译器看到了&,然后就报错了,因为就像&1一样,编译器不知道你取一个常量的地址算几个意思

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值