指针和数组笔试题解析

int a[] = {1,2,3,4};
//printf("%d\n", sizeof(arr));//16     sizeof求的是字节,一个int类型占四个字节。
	//printf("%d\n", sizeof(arr + 0));//4     当前由于数组名参与了+0的运算,隐式转成了指针。
	//printf("%d\n", sizeof(*arr));// 4  当前arr参与*运算,也隐式转成了指针int* ,针对int*解引用,结果是一个int
	//printf("%d\n", sizeof(arr + 1));//4       当前由于数组名参与了+1的运算,隐式转成了指针。
	//printf("%d\n", sizeof(arr[1]));//4      arr是数组,[1]取到下标为1的元素,是一个int
	//printf("%d\n", sizeof(&arr));//4     &arr是一个数组指针,int(*)[4],只要是指针
	//不管是什么指针,都是占四个字节.指针里面存放的都是地址。
	//printf("%d\n", sizeof(*&arr));//16     &arr得到一个数组指针,int(*)[4],然后针对这个数组指针*操作,
	//结果就得到了一个int [4]
	//printf("%d\n", sizeof(&*arr));//4      当前arr是int [4],*a,其实就是先把a转成一个int*,
	//然后*得到了一个int.然后又取地址,又得到了一个int*
	//printf("%d\n", sizeof(&arr + 1));//4     &arr是一个数组指针,int(*)[4],再+1,仍然是int(*)[4]
	//printf("%d\n", sizeof(&arr[0]));// 4    arr是一个int[4],arr[0]是int,再&就是int*
	//printf("%d\n", sizeof(&arr[0] + 1));//4   arr是一个int[4],arr[0]是int,再&就是int*,再+1仍然是int*
	

只要在算指针的sizeof,都是4;

数组名,在很多情况下会隐式转成指针类型;(指向数组首元素的指针)

1.函数调用

2.参与运算(+-,*,==,<,>,>=......)

字符串和字符数组不一样,并不是等价关系。

字符串是一种特殊的字符数组,里面必须带\0;

如果没有带\0,就绝对不是字符串。

sizeof是在求一个变量在内存中占几个字节。

strlen是在求一个字符串的长度。(从传入字符串的起始位置开始,找\0)

sizeof与strlen是没有任何关系的!

 unsigned

printf("%d\n",strlen(*arr));

在函数调用的时候,需要保证形参和实参是类型是匹配的。

char与const char*不匹配。按理说应该要编译出错,但是在C语言中存在隐式类型转换。就会在传参的时候尝试把char转成const char*.相当于把‘a’这个ASCIL当成了一个具体的地址了。(这个地址是非法地址,尝试读取这个地址,就容易出现未定义行为)。

 

int main(){
	char arr[] = { 'a','b','c','d','e','f' };
	//printf("%d\n", sizeof(arr));//6   没有\0
	//printf("%d\n", sizeof(arr+0));//4   arr本来是char[6],但是进行了+0操作,就隐式转成了char*是一个指针
	//printf("%d\n", sizeof(*arr));//1     arr是char[6],本来是一个数组,但是在*运算中也隐式转成了char*
	//针对char*进行*解引用,结果就变成了char
	//printf("%d\n", sizeof(arr[1]));//1   arr是char[6]进行[1]操作,就得到了char ‘b’
	//printf("%d\n", sizeof(&arr));//4    arr本来是arr[6],进行&运算之后,就得到了char(*)[6]  是一个数组指针。
	//printf("%d\n", sizeof(&arr+1));//4    arr本来是arr[6],进行&运算之后,就得到了char(*)[6]  再+1,
	//仍然是char(*)[6]
	//printf("%d\n", sizeof(&arr[0] + 1));//4    arr[0]得到字符‘a’,然后&,变成了char* char*+1,
	//依然还是char*,是一个指针
	
	//代码中永远不能依赖未定义行为。
	//printf("%d\n", strlen(arr));//未定义行为,arr没有\0,进行strlen就会出现数组下标越界的情况。
	//printf("%d\n", strlen(arr + 0)); //未定义行为
	//printf("%d\n", strlen(*arr));//未定义行为 arr是char[6],*arr得到的是char,‘a’这个字符
	//把‘a'的ASCIL的值对应的内存。
	//printf("%d\n", strlen(arr[1]));//同上,这次访问的是‘b’的ASCIL的值对应的内存。
	//printf("%d\n", strlen(&arr)); //未定义行为  得到的是char(*)[6],是一个数组指针。
	//虽然和形参类型不同,但是大家都是指针,里面存的地址相同,这个时候也就相当于是从‘a’地址开始往后找\0
	//printf("%d\n", strlen(&arr + 1));//未定义行为     得到的是char(*)[6],是一个数组指针,再+1,
	//仍然还是数组指针,指针+1,地址就跳过一个元素。这一跳就把整个数组元素都给跳过了。
	printf("%d\n", strlen(&arr[0] + 1));//

 char(*)[6]和char(*)[7]是不同类型的。指针的类型是描述房间的大小。

int main(){
	//“”本身已经是字符串了,本身里面已经有\0了。
	//得到的arr应该是一个char[7].
	char arr[] = "abcdef";
	//printf("%d\n", sizeof(arr));//7
	//printf("%d\n", sizeof(arr + 0));//4   相当于隐式转成了char*
	//printf("%d\n", sizeof(*arr));// 1     *arr得到的是‘a’,char
	//printf("%d\n", sizeof(arr[1]));//1      'b',char
	//printf("%d\n", sizeof(&arr));//  4    arr得到的是 char[7],&得到char(*)[7]数组指针。
	//printf("%d\n", sizeof(&arr + 1));//4     同上
	//printf("%d\n", sizeof(&arr[0] + 1));//4      char[0]得到的是char,再&得到char*

int main(){
	//“”本身已经是字符串了,本身里面已经有\0了。
	//得到的arr应该是一个char[7].
	char arr[] = "abcdef";
	//printf("%d\n", strlen(arr));//6         计算strlen的时候不计算\0;
	//printf("%d\n", strlen(arr + 0));//6
	//printf("%d\n", strlen(*arr));//未定义行为,*arr得到的是‘a’,char,不是const char*
	//printf("%d\n", strlen(arr[1]));//未定义行为,得到的是‘b’
	//printf("%d\n", strlen(&arr));//6      得到的是数组指针,char(*)[7]和形参要求的const char*不同的。
	//虽然类型不匹配,但是结果碰巧是对的。
	//printf("%d\n", strlen(&arr + 1));
	//printf("%d\n", strlen(&arr[0] + 1));//5   arr[0]得到字符‘a’,再&得到的了指向‘a’的指针。
	//+1就得到了指向‘b’的指针,从'b'开始找\0

指针的[]相当于*解引用的简化写法

int main(){
	char* p = "abcdef";
	//printf("%d\n", sizeof(p));//4    char*类型
	//printf("%d\n", sizeof(p + 1));//4   还是char*类型    
	//printf("%d\n", sizeof(*p));//1        是char类型
	//printf("%d\n", sizeof(p[0]));//1        指针同样也支持[]操作,p[0]相当于*(p+0)
	//指针的[]相当于*解引用的简化写法。
	//printf("%d\n", sizeof(&p));//4       p是char*,&p之后的类型是char**;
	//printf("%d\n", sizeof(&p + 1));//4           char**+1还是char**
	//printf("%d\n", sizeof(&p[0] + 1));//4      p[0]得到char, &char得到的是char*

//printf("%d\n", strlen(*p));//未定义行为,*arr得到的是‘a’,char,不是const char*,
    // 从'a'开始找\0,但是97是没有申请到地址,strlen需要的是char*类型。
    // 原则上讲是不应该编译通过的,但是c语言对于类型的检查是不严格的。
    // strlen就会尝试从‘a’的ASCIL这个地址开始找\0

/*char* p = "abcdef";*/
	//printf("%d\n", strlen(p));//6         从a开始找\0
	//printf("%d\n", strlen(p + 1));//5       从b开始找\0
	//printf("%d\n", strlen(*p));//未定义行为,*arr得到的是‘a’,char,不是const char*,
	// 从'a'开始找\0,但是97是没有申请到地址,strlen需要的是char*类型。
	// 原则上讲是不应该编译通过的,但是c语言对于类型的检查是不严格的。
	// strlen就会尝试从‘a’的ASCIL这个地址开始找\0
	//printf("%d\n", strlen(p[0]));//也是属于未定义行为。
	//printf("%d\n", strlen(&p));//未定义行为        char**类型
	//printf("%d\n", strlen(&p + 1));//未定义行为  &p得到的是char**, 本身内部存的地址,是p变量本身的地址。
	// 这个地址和\0无关,尝试去找,能不能找到这个\0是完全不知道的。
	//printf("%d\n", strlen(&p[0] + 1));//5    p[0]得到的是char ‘a’,指向‘a’,再+1得到的是指向‘b’的指针。

二维数组本质上也是一个一维数组,每一个元素还是一个一维数组。

针对二维数组取下标(只有一个【0】),得到的是里面的一个元素,仍然是一个一维数组。

int a[3][4];

长度为3的一维数组,每个元素又是长度为4的一维数组。

a[0]=int [4]=>sizeof   16

*(a[0]+1)=>a[0][1];

//printf("%d\n", sizeof(a + 1));// 4      int[3][4],a+1就是数组名,在进行+1的时候,会隐式转成指针。
    // 首元素是int[4]
    //指向首元素的指针int(*)[4]    数组指针。

*(a+1)=a[1];        

*a = *(a+0)=a[0];

总结:
数组名的意义:
1. sizeof( 数组名 ) ,这里的数组名表示整个数组,计算的是整个数组的大小
2. & 数组名,这里的数组名表示整个数组,取出的是整个数组的地址
3. 除此之外所有的数组名都表示首元素的地址

char* const p; p为指向字符变量的指针,地址不变,地址内容可变

const char *p; p为指向字符变量的指针,地址可变,地址内容不变

char const *p 与const char *p等价。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

穿狼皮的小红帽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值