十二.指针详解(4)

10.数组和指针试题讲解

数组

整型数组

#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:6328)
#include <stdio.h>
int main()
{
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));//sizeof(数组名):计算的是整个数组的大小 ———— 16
	printf("%d\n", sizeof(a+0));//a+0表示a是首元素的地址,所以大小为 ———— 4/8(32位平台(x86)是4字节,64位平台(x64)是8字节)
	printf("%d\n", sizeof(*a));//a是首元素地址,*a就是首元素,整型元素大小为 ———— 4
	printf("%d\n", sizeof(a+1));//a+1是第二个元素的地址 ———— 4/8
	printf("%d\n", sizeof(a[1]));//第二个元素的大小 ———— 4
	printf("%d\n", sizeof(&a));//&a取的是整个数组的地址,但也是地址,是地址就是 ———— 4/8
	printf("%d\n", sizeof(*&a));//对整个数组的地址解引用,还可以理解为*和&抵消了 ———— 16
	printf("%d\n", sizeof(&a+1));//&a+1表示地址跳过一整个数组,但仍是地址 ———— 4/8
	printf("%d\n", sizeof(&a[0]));//取出首元素的地址 ———— 4/8
	printf("%d\n", sizeof(&a[0]+1));//第二个元素的地址 ———— 4/8

	return 0;
}

运行结果:

16
8
4
8
4
8
16
8
8
8

-- -- -- -- -- -- -- -- -- --

字符数组

例一
#include <stdio.h>
#pragma warning(disable:6328)
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));//sizeof(数组名):计算的是整个数组的大小 ———— 6
	printf("%d\n", sizeof(arr+0));//a+0表示a是首元素的地址,所以大小为 ———— 4/8
	printf("%d\n", sizeof(*arr));//a是首元素地址,*a就是首元素,字符类型元素大小为 ———— 1
	printf("%d\n", sizeof(arr[1]));//第二个元素的大小 ———— 1
	printf("%d\n", sizeof(&arr));//&a取的是整个数组的地址,但也是地址,是地址就是 ———— 4/8
	printf("%d\n", sizeof(&arr+1));//&a+1表示地址跳过一整个数组,但仍是地址 ———— 4/8
	printf("%d\n", sizeof(&arr[0]+1));//第二个元素的地址 ———— 4/8
	return 0;
}

运行结果:

6
8
1
1
8
8
8

-- -- -- -- -- -- -- 

例二
#include <stdio.h>
#include <string.h>
#pragma warning(disable:4477)
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", strlen(arr));//无'\0',结果是 ———— 随机值
	printf("%d\n", strlen(arr + 0));//首元素地址+0,但仍然没有'\0',结果是 ———— 随机值(和上面一样)
	printf("%d\n", strlen(*arr));//strlen函数的参数部分要的是地址,而*arr等于a,a的ACSCII码值是97
	//strlen会从97这个地址向后去找'\0',属于非法访问,直接报错 ———— error
	printf("%d\n", strlen(arr[1]));//传了一个b(即98)给strlen函数 ———— error
	printf("%d\n", strlen(&arr));//整个数组的地址在值上等于字符'a'的地址,所有也是从开头去找'\0', ———— 随机值
	printf("%d\n", strlen(&arr+1));//地址跳过一个数组后,在想后面找'\0',随机值小6 ———— 上面的随机值-6
	printf("%d\n", strlen(&arr[0]+1));//从第二个元素向后面找'\0',随机值小1 ———— 随机值-1
	return 0;
}

可能有的编译器会说strlen的需要参数和传过来的不一样,直接报错,这个会在下面的例四中一起回答这个问题

-- -- -- -- -- -- -- 

例三
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#pragma warning(disable:4477)
int main()
{
	char arr[] = "abcdef";
	printf("%d\n", sizeof(arr));//f后面还有'\0',共7个char类型的元素 ———— 7
	printf("%d\n", sizeof(arr + 0));//首元素地址+0还是地址 ———— 4/8
	printf("%d\n", sizeof(*arr));//首元素大小 ———— 1
	printf("%d\n", sizeof(arr[1]));//第2个元素大小 ———— 1
	printf("%d\n", sizeof(&arr));//整个数组的地址 ———— 4/8
	printf("%d\n", sizeof(&arr + 1));//跳过一个数组的地址 ———— 4/8
	printf("%d\n", sizeof(&arr[0] + 1));//第二个元素的地址 ———— 4/8
	return 0;
}

运行结果:

7
8
1
1
8
8
8

-- -- -- -- -- -- -- 

例四
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#pragma warning(disable:4477)
int main()
{
	char arr[] = "abcdef";
	printf("%d\n", strlen(arr));//'\0'前共有6个字符 ———— 6
	printf("%d\n", strlen(arr + 0));//arr+0仍是首元素地址,与上一行相同 ———— 6
	printf("%d\n", strlen(*arr));//传参传了一个'a'(即97),非法访问 ———— error
	printf("%d\n", strlen(arr[1]));//非法访问 ———— error
	printf("%d\n", strlen(&arr));//整个数组的地址在值上和首元素地址相同,结果还是 ———— 6
	//但是会报警告(报错也可能)。因为&arr的类型是数组指针char(*)[7],但是strlen函数的参数是const char*
	printf("%d\n", strlen(&arr + 1));//跳过一个数组的地址。因此,连数组末尾的'\0'都跳过了,不知道下一个'\0'会在哪 ———— 随机值
	printf("%d\n", strlen(&arr[0] + 1));//从'b'开始向后面开始找'\0' ———— 5
	return 0;
}

-- -- -- -- -- -- -- 

例五
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#pragma warning(disable:4477)
int main()
{
	const char* p = "abcdef";//有点编译器不支持这样写:char* p = "abcdef" ,你在前面加一个const就好了,加完也更加严谨
	printf("%d\n", sizeof(p));//p是指针 ———— 4/8
	printf("%d\n", sizeof(p + 1));//p+1是地址 ———— 4/8
	printf("%d\n", sizeof(*p));//*p就是字符a ———— 1
	printf("%d\n", sizeof(p[0]));//数组中arr[0]就等于*(arr+0),这里p==arr,它们都是首元素地址,p[0]==*(p+0).所有p[0]其实就是a ———— 1
	printf("%d\n", sizeof(&p));//p是一级指针,&p可以放在一个二级指针里 ———— 4/8
	printf("%d\n", sizeof(&p + 1));//p的地址+1 ———— 4/8
	printf("%d\n", sizeof(&p[0] + 1));//p[0]是a,&p[0]就是a的地址,加1是b的地址 ———— 4/8

	return 0;
}

运行结果:

8
8
1
1
8
8
8

-- -- -- -- -- -- -- 

例六
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#pragma warning(disable:4477)
int main()
{
	const char* p = "abcdef";
	printf("%d\n", strlen(p));//p中是首元素地址,这个字符串常量有六个字符 ———— 6
	printf("%d\n", strlen(p + 1));//strlen从b开始向后找'\0' ———— 5
	printf("%d\n", strlen(*p));//非法访问 ———— error
	printf("%d\n", strlen(p[0]));//非法访问 ———— error
	printf("%d\n", strlen(&p));//从p的地址向后找'\0' ———— 随机值
	printf("%d\n", strlen(&p + 1));//p的地址的下一个地址 ———— 随机值
	printf("%d\n", strlen(&p[0] + 1));//从b的地址向后找'\0' ———— 5
	return 0;
}

-- -- -- -- -- -- -- -- -- --

二维数组

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#pragma warning(disable:4477)
int main()
{
    int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));//求数组大小,12*4 ———— 48
	printf("%d\n", sizeof(a[0][0]));//第一行第一列那个元素的大小 ———— 4
	printf("%d\n", sizeof(a[0]));//把二维数组看成一维数组,每个元素都是一维数组,a[0]即为第一行的数组名,sizeof求第一行四个元素的大小,4*4 ———— 16
	printf("%d\n", sizeof(a[0] + 1));//a[0]+1中,数组名表示首元素地址,+1则是第一行第二列的元素地址,而不是第二行的地址 ———— 4/8
	printf("%d\n", sizeof(*(a[0] + 1)));//第一行第二列的元素 ———— 4
	printf("%d\n", sizeof(a + 1));//a是二维数组的数组名,所以a就是首元素(第一行)地址,a+1就是第二行地址 ———— 4/8
	printf("%d\n", sizeof(*(a + 1)));//第二行的大小,等于arr[1] ———— 16
	printf("%d\n", sizeof(&a[0] + 1));//&a[0]取出第一行的地址,+1则是第二行的地址 ———— 4/8
	printf("%d\n", sizeof(*(&a[0] + 1))); //由上一行可知,这是在求第二行的大小 ———— 16
	printf("%d\n", sizeof(*a));//第一行的大小 ———— 16
	printf("%d\n", sizeof(a[3]));//sizeof不会去访问数组的地址行,它是不参与真实运算的,只是根据类型来计算大小。
	//所以a[3]和a[0]是一样的,是一个有4个整型元素的一维数组 ———— 16
	return 0;
}

运行结果:

48
4
16
8
4
8
16
8
16
16
16
 

-- -- -- -- -- -- -- -- -- -- -- -- -- -- ---- -- -- -- -- -- -- -- -- -- -- -- -- -- --

①作者当前使用x64平台,所以指针大小为8

#pragma百度百科

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

世长老

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

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

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

打赏作者

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

抵扣说明:

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

余额充值