c语言分层理解(c语言指针笔试题解析)

前言

经过了一天的写作,终于完成了这一篇,对指针进行了练习,感觉很爽,分享一下!还望大佬多多关注!

1. 一维数组和指针

1.1 例题

int main()
{
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a + 0));
	printf("%d\n", sizeof(*a));
	printf("%d\n", sizeof(a + 1));
	printf("%d\n", sizeof(a[1]));
	printf("%d\n", sizeof(&a));
	printf("%d\n", sizeof(*&a));
	printf("%d\n", sizeof(&a + 1));
	printf("%d\n", sizeof(&a[0]));
	printf("%d\n", sizeof(&a[0] + 1));
	return 0;
}

1.2 解析

#include <stdio.h>
int main()
{
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));
	//结果:16字节
	//解释:数组名单独放在sizeof内部计算的是整个数组的大小,单位是字节

	printf("%d\n", sizeof(a + 0));
	//结果:4/8字节
	//解释:数组名并没有单独放在sizeof内部,所以a就是首元素地址,a+0也是首元素地址,所以计算的是一个指针的大小,单位是字节,
	//     千万不能把sizeof(a+0)当作sizeof(a)来计算

	printf("%d\n", sizeof(*a));
	//结果:4字节
	//解释:数组名并没有单独放在sizeof内部,所以a就是首元素地址,对int*指针进行解引用,拿到的是一个int类型的元素,sizeof(*a)=sizeof(int),单位是字节

	printf("%d\n", sizeof(a + 1));
	//结果:4/8字节
	//解释:数组名并没有单独放在sizeof内部,所以a就是首元素地址,因为a是int*指针,所以a+1就跳过一个int类型的元素,
	//     a+1也就是指向数组第二个元素的是指针,所以sizeof(a+1)计算的是指针的大小,单位是字节

	printf("%d\n", sizeof(a[1]));
	//结果:4字节
	//解释:a[1]拿到的是小标为1的元素,元素类型是int类型,所以sizeof(a[1])=sizeof(int),单位是字节

	printf("%d\n", sizeof(&a));
	//结果:4/8字节
	//解释:&a就是取到的整个数组的地址,是一个指向整个数组的指针,所以sizeof(&a)计算的就是指针大小,单位是字节

	printf("%d\n", sizeof(*&a));
	//结果:16字节
	//解释:*&a也就是先拿到数组a的整个数组的地址,再对&a解引用,拿到的是整个数组的大小,所以sizeof(*&a)=sizeof(a),单位是字节

	printf("%d\n", sizeof(&a + 1));
	//结果:4/8字节
	//解释:&a+1也就是拿到整个数组的地址,整个数组的指针类型是一个数组指针类型,&a+1也就跳过一个数组的大小,得到的仍然是地址,地址就是指针,
	//     所以sizeof(&a+1)也就是计算指针的大小,单位是字节

	printf("%d\n", sizeof(&a[0]));
	//结果:4/8字节
	//解释:&a[0]也就是拿到下标为0的元素的地址,也就是拿到第一个元素的地址,地址就是指针,所以sizeof(&a[0])计算的就是指针的大小

	printf("%d\n", sizeof(&a[0] + 1));
	//结果:4/8字节
	//解释:&a[0]+1,也就是拿到第一个元素的地址,再跳过这个元素,拿到下一个元素的地址,地址就是指针,所以sizeof(&a[0]+1)计算的就是指针的大小

	return 0;
}

1.3 输出结果

1.3.1 32位平台

1.3.1 64位平台

2. 字符数组和指针

2.1 形式1(char arr[] = {‘#’,‘#’,‘#’,‘#’,‘#’})

2.1.1 例题

#include <stdio.h>
#include <string.h>
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr + 0));
	printf("%d\n", sizeof(*arr));
	printf("%d\n", sizeof(arr[1]));
	printf("%d\n", sizeof(&arr));
	printf("%d\n", sizeof(&arr + 1));
	printf("%d\n", sizeof(&arr[0] + 1));
	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr + 0));
	printf("%d\n", strlen(*arr));
	printf("%d\n", strlen(arr[1]));
	printf("%d\n", strlen(&arr));
	printf("%d\n", strlen(&arr + 1));
	printf("%d\n", strlen(&arr[0] + 1));
	return 0;
}

2.1.2 解析

#include <stdio.h>
#include <string.h>
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));
	//结果:6字节
	//解释:arr是数组名,单独的数组名在sizeof内部,计算的是数组的大小,数组只分配了6个字节的空间,所以数组大小是6,单位是字节

	printf("%d\n", sizeof(arr + 0));
	//结果:4/8字节
	//解释:arr是数组名,但是并没有单独在sizeof内部,所以arr是首元素地址,arr+0拿到的还是首元素的地址,地址就是指针,所以sizeof计算的是指针的大小,单位是字节

	printf("%d\n", sizeof(*arr));
	//结果:1字节
	//解释:arr是数组名,但是并没有单独在sizeof内部,所以arr是首元素地址,指针类型是char*,对指针解引用就拿到第一个元素,
	//     第一个元素的大小是1个字节,sizeof(*arr)=sizeof(arr[0])

	printf("%d\n", sizeof(arr[1]));
	//结果:1字节
	//解释:arr[1]就是下标为1的元素,也就是数组中第二个元素,元素类型是char,所以sizeof(arr[1])=sizeof(char),单位是字节

	printf("%d\n", sizeof(&arr));
	//结果:4/8字节
	//解释:&arr,拿到的是整个数组的地址,地址就是指针,所以sizeof(&arr)计算的是指针的大小

	printf("%d\n", sizeof(&arr + 1));
	//结果:4/8字节
	//解释:&arr,拿到的是整个数组的地址,地址就是指针,指针类型是数组指针类型,指向的是整个数组,&arr+1也就是跳过一个数组指针的大小,
	//     也就是跳一个数组,得到的仍然是一个地址,地址就是指针,所以sizeof(&arr+1)计算的就是指针的大小,单位是字节

	printf("%d\n", sizeof(&arr[0] + 1));
	//结果:4/8字节
	//解释:&arr[0]得到的是一个下标为0的元素的地址,也就是得到的是数组中第一个元素的地址,地址就是指针,指针类型是int*,&arr[0]+1,
	//     跳过的就是一个整形的大小,得到的仍然是一个地址,地址就是指针,单位是字节

	//strlen库函数计算的是字符串中字符'\0'之前的元素个数
	printf("%d\n", strlen(arr));
	//结果:随机值
	//解释:strlen库函数计算的是字符串中字符'\0'之前的元素个数,但是在数组中我们用的是一块连续的空间,
	//     这块空间的后面都是随机值,arr是数组名,是首元素地址,从数组名这个地址向下找到'\0'字符,在此数组内部这6个元素中没有'\0',
	//     就在数组内存空间的后面继续查找'\0'字符,直到找到'\0'结束,所以这是一个随机值,不确定

	printf("%d\n", strlen(arr + 0));
	//结果:随机值
	//解释:arr是数组名,是首元素地址,arr+0仍然是首元素地址,strlen库函数计算的是字符串中字符'\0'之前的元素个数,
	//     所以要从数组名这个地址向下找到'\0'字符,内存是随机分配的数据,所以不知道'\0'字符的位置,所以是随机值。

	printf("%d\n", strlen(*arr));
	//结果:err
	//解释:arr是首元素地址,*arr就是对第一个元素解引用得到字符'a','a'的ASCII值是97,strlen库函数就是把97当作地址访问,这里是非法访问。

	printf("%d\n", strlen(arr[1]));
	//结果:err
	//解释:arr[1]得到的就是数组的第二个元素'b','b'的ASCII值是98,strlen库函数把98当作地址,非法访问。

	printf("%d\n", strlen(&arr));
	//结果:随机值
	//解释:&arr得到的是整个数组的地址,也就是数组的起始地址,一样也是随机值,不知道'\0'在内存的哪里。

	printf("%d\n", strlen(&arr + 1));
	//结果:随机值
	//解释:&arr得到的是整个数组的地址,地址就是指针,指针类型是一个数组指针类型,&arr+1跳过的是整个数组,同样从数组的末尾地址向下寻找'\0'字符,
	//     任然是个随机值,不确定'\0'在内存中的位置。

	printf("%d\n", strlen(&arr[0] + 1));
	//结果:随机值
	//解释:&arr[0]拿到的是数组第一个元素的地址,地址就是指针,类型是char*,跳过一个char大小,也就得到第二个元素的地址,
	//     在内存中往下寻找'\0'字符,不知道内存中'\0'的位置,所以是随机值。

	return 0;
}

2.1.3 输出结果

说明:因为有两个是error的,所以屏蔽了这两段代码。具体显示是strlen库函数中函数参数是const char*的和这里的char的参数不一致,同时这里的隐藏错误就是非法访问地址。

2.1.3.1 32位平台

2.1.3.2 64位平台

2.2 形式2(char arr[] = “####”)

2.2.1 例题

#include <stdio.h>
#include <string.h>
int main()
{
	char arr[] = "abcdef";
	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr + 0));
	printf("%d\n", sizeof(*arr));
	printf("%d\n", sizeof(arr[1]));
	printf("%d\n", sizeof(&arr));
	printf("%d\n", sizeof(&arr + 1));
	printf("%d\n", sizeof(&arr[0] + 1));
	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr + 0));
	printf("%d\n", strlen(*arr));
	printf("%d\n", strlen(arr[1]));
	printf("%d\n", strlen(&arr));
	printf("%d\n", strlen(&arr + 1));
	printf("%d\n", strlen(&arr[0] + 1));
	return 0;
}

2.2.2 解析

#include <stdio.h>
#include <string.h>
int main()
{
	char arr[] = "abcdef";
	printf("%d\n", sizeof(arr));
	//结果:7字节
	//解释:arr数组名单独放在sizeof内部,计算的是整个数组大小,数组包含abcdef\07个字符,所以是7个字节大小

	printf("%d\n", sizeof(arr + 0));
	//结果:4/8字节
	//解释:arr不是单独放在sizeof内部,所以arr是首元素地址,arr+0仍然是首元素地址,地址就是指针,sizeof(arr+0)计算的就是指针的大小,单位是字节

	printf("%d\n", sizeof(*arr));
	//结果:1字节
	//解释:*arr拿到的是第一个元素,元素类型是char,所以sizeof(*arr)=sizeof(char),单位是字节

	printf("%d\n", sizeof(arr[1]));
	//结果:1字节
	//解释:arr[1]拿到的是数组中第二个元素,类型是char,所以sizeof(arr[1])=sizeof(char),单位是字节

	printf("%d\n", sizeof(&arr));
	//结果:4/8字节
	//解释:&arr拿到的是整个数组的地址,地址就是指针,所以sizeof(&arr)计算的就是指针的大小

	printf("%d\n", sizeof(&arr + 1));
	//结果:4/8字节
	//解释:&arr拿到的是整个数组的地址,地址就是指针,指针类型是数组指针,&arr+1跳过的是整个数组,仍然得到的是地址,地址就是指针,所以sizeof(&arr+1)计算的就是指针的大小

	printf("%d\n", sizeof(&arr[0] + 1));
	//结果:4/8字节
	//解释:&arr[0]得到的是一个下标为0的元素的地址,也就是得到的是数组中第一个元素的地址,地址就是指针,指针类型是char*,&arr[0]+1,
	//     跳过的就是一个字符型的大小,得到的仍然是一个地址,地址就是指针,单位是字节

	printf("%d\n", strlen(arr));
	//结果:6字节
	//解释:strlen是计算'\0'之前的元素个数,字符串结束标志就是'\0',元素个数是6,所以strlen(arr)=6,单位是字节

	printf("%d\n", strlen(arr + 0));
	//结果:6字节
	//解释:arr是数组名,也就是首元素地址,从字符串第一个元素向后找到'\0'结束,字符串结束标志是'\0',所以strlen(arr+0)=6,单位是字节

	printf("%d\n", strlen(*arr));
	//结果:err
	//解释:arr是数组名,也就是首元素地址,*arr拿到第一个元素'a','a'的ASCII值是97,strlen库函数就是把97当作地址访问,这里是非法访问。

	printf("%d\n", strlen(arr[1]));
	//结果:err
	//解释:arr[1]得到的就是数组的第二个元素'b','b'的ASCII值是98,strlen库函数把98当作地址,非法访问。

	printf("%d\n", strlen(&arr));
	//结果:6字节
	//解释:&arr得到的是整个数组的地址,也就是数组的起始地址,一样向后找到'\0'停止,strlen(&arr)=6,单位是字节

	printf("%d\n", strlen(&arr + 1));
	//结果:随机值
	//解释:&arr得到的是整个数组的地址,地址就是指针,指针类型是一个数组指针类型,&arr+1跳过的是整个数组,同样从数组的末尾地址向下寻找'\0'字符,
	//     任然是个随机值,不确定'\0'在内存中的位置。

	printf("%d\n", strlen(&arr[0] + 1));
	//结果:5字节
	//解释:&arr[0]拿到的是数组第一个元素的地址,地址就是指针,类型是char*,跳过一个char大小,也就得到第二个元素的地址,
	//     在内存中往下寻找'\0'字符,字符串结束表示'\0',所以strlen(&arr[0] + 1))=5,单位是字节

	return 0;
}

2.2.3 输出结果

说明:说明:因为有两个是error的,所以屏蔽了这两段代码。具体显示是strlen库函数中函数参数是const char*的和这里的char的参数不一致,同时这里的隐藏错误就是非法访问地址。

2.2.3.1 32位平台

2.2.3.2 64位平台

2.3 形式3(char* p = “####”)

2.3.1 例题

#include <stdio.h>
#include <string.h>
int main()
{
	char* p = "abcdef";
	printf("%d\n", sizeof(p));
	printf("%d\n", sizeof(p + 1));
	printf("%d\n", sizeof(*p));
	printf("%d\n", sizeof(p[0]));
	printf("%d\n", sizeof(&p));
	printf("%d\n", sizeof(&p + 1));
	printf("%d\n", sizeof(&p[0] + 1));
	printf("%d\n", strlen(p));
	printf("%d\n", strlen(p + 1));
	printf("%d\n", strlen(*p));
	printf("%d\n", strlen(p[0]));
	printf("%d\n", strlen(&p));
	printf("%d\n", strlen(&p + 1));
	printf("%d\n", strlen(&p[0] + 1));
	return 0;
}

2.3.2 解析

#include <stdio.h>
#include <string.h>
int main()
{
	char* p = "abcdef";
	printf("%d\n", sizeof(p));
	//结果:4/8字节
	//解释:p是字符串首元素地址,地址就是指针,指针类型是char*,所以sizeof(p)计算的是指针的大小

	printf("%d\n", sizeof(p + 1));
	//结果:4/8字节
	//解释:p是字符串首元素地址,地址就是指针,指针类型是char*,p+1就跳过一个char大小,也就是得到第二个元素'b'的地址,
	//     地址就是指针,所以sizeof(p+1)计算的就是指针的大小,单位是字节

	printf("%d\n", sizeof(*p));
	//结果:1字节
	//解释:p是字符串首元素地址,地址就是指针,对p解引用拿到'a','a'的类型就是char,所以sizeof(*p)=sizeof(char),单位是字节

	printf("%d\n", sizeof(p[0]));
	//结果:1字节
	//解释:p是字符串首元素地址,也就相当于数组名,p[0]拿到的是第一个元素'a','a'的类型是char,所以sizeof(p[0])=sizeof(char),单位是字节

	printf("%d\n", sizeof(&p));
	//结果:4/8字节
	//解释:p是字符串首元素地址,地址就是指针,&p得到的是一个二级指针,所以sizeof(&p)计算的就是指针的大小,单位是字节

	printf("%d\n", sizeof(&p + 1));
	//结果:4/8字节
	//解释:p是字符串首元素地址,地址就是指针,&p得到的是一个二级指针,二级指针类型是char**,&p+1跳过一个char*大小,得到的仍然是一个地址,地址就是指针,所以siezof(&p+1)计算的就是指针大小

	printf("%d\n", sizeof(&p[0] + 1));
	//结果:4/8字节
	//解释:p是字符串首元素地址,也就相当于数组名,p[0]拿到的是第一个元素'a',&p[0]就是拿到第一个元素的地址,地址就是指针,指针类型是char*,&p[0]+1跳过一个char类型大小,也就是拿到第二个元素'b'的地址,地址就是指针,所以sizeof(&p[0]+1)计算的就是指针大小

	printf("%d\n", strlen(p));
	//结果:6字节
	//解释:p是字符串首元素地址,也就相当于数组名,strlen是计算'\0'之前的元素个数,字符串结束标志就是'\0',元素个数是6,所以strlen(arr)=6,单位是字节

	printf("%d\n", strlen(p + 1));
	//结果:5字节
	//解释:p是首元素地址,地址就是指针,指针类型是char*,p+1跳过一个char大小,得到的是第二个元素'b'的地址,strlen是计算'\0'之前的元素个数,字符串结束标志就是'\0',所以strlen(p+1)=5

	printf("%d\n", strlen(*p));
	//结果:err
	//解释:p是首元素地址,地址就是指针,指针类型是char*,对其解引用拿到'a'字符,'a'的ASCII值是97,strlen库函数就是把97当作地址访问,这里是非法访问。

	printf("%d\n", strlen(p[0]));
	//结果:err
	//解释:p是字符串首元素地址,也就相当于数组名,p[0]拿到的是第一个元素'a','a'的ASCII值是97,strlen库函数就是把97当作地址访问,这里是非法访问。

	printf("%d\n", strlen(&p));
	//结果:随机值
	//解释:p是字符串首元素地址,地址就是指针,&p得到的是一个二级指针,二级指针类型是char**,地址不是从p开始向下寻找了,所以不知道内存中'\0'的位置,所以是随机值,单位是字节

	printf("%d\n", strlen(&p + 1));
	//结果:随机值
	//解释:p是字符串首元素地址,地址就是指针,&p得到的是一个二级指针,二级指针类型是char**,跳过一个char*大小,得到的地址也不是从p开始向下寻找了,
	//     所以不知道内存中'\0'的位置,所以是随机值,单位是字节

	printf("%d\n", strlen(&p[0] + 1));
	//结果:5字节
	//解释:p是字符串首元素地址,也就相当于数组名,p[0]拿到的是第一个元素'a',&p[0]拿到第一个元素'a'的地址,地址就是指针,指针类型是char*,&p[0]+1就是跳过一个char大小,得到第二个元素'b'的地址,从这里往后找,找到'\0'停止,字符串结束标志是'\0',所以strlen(&p[0] + 1))=5,单位是字节

	return 0;
}

2.3.3 输出结果

说明:因为有两个是error的,所以屏蔽了这两段代码。具体显示是strlen库函数中函数参数是const char*的和这里的char的参数不一致,同时这里的隐藏错误就是非法访问地址。

2.3.3.1 32位平台

2.3.3.2 64位平台

3. 二维数组和指针

3.1 例题

#include <stdio.h>
int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a[0][0]));
	printf("%d\n", sizeof(a[0]));
	printf("%d\n", sizeof(a[0] + 1));
	printf("%d\n", sizeof(*(a[0] + 1)));
	printf("%d\n", sizeof(a + 1));
	printf("%d\n", sizeof(*(a + 1)));
	printf("%d\n", sizeof(&a[0] + 1));
	printf("%d\n", sizeof(*(&a[0] + 1)));
	printf("%d\n", sizeof(*a));
	printf("%d\n", sizeof(a[3]));
	return 0;
}

3.2 解析

#include <stdio.h>
int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));
	//结果:48字节
	//解释:a是数组名,数组名单独放在sizeof内部,计算的是整个二维数组大小,所以sizeof(a)=4*3*4=48,单位是字节

	printf("%d\n", sizeof(a[0][0]));
	//结果:4字节
	//解释:a[0][0]得到的第一行第一列的元素,元素类型是int,所以sizeof(a[0][0])=sizeof(int)=4,单位是字节

	printf("%d\n", sizeof(a[0]));
	//结果:16字节
	//解释:a[0]表示二维数组的第一行,第一行是一个有四个元素的一维数组,在二维数组中a[0]就相当于一维数组名,
	//     数组名单独放在sizeof内部,计算的是整个一维数组的大小,a[0]类型是int [4],所以sizeof(a[0])=4*4=16,单位是字节

	printf("%d\n", sizeof(a[0] + 1));
	//结果:4/8字节
	//解释:a[0]表示二维数组的第一行,,第一行是一个有四个元素的一维数组,在二维数组中a[0]就相当于一维数组名,并不是单独放在二维数组中,所以他就是一维数组首元素地址,地址就是指针,
	//     指针类型是int*,a[0]+1就是跳过一个int大小,得到a[0][1]的地址,地址就是指针,所以sizeof(a[0]+1)计算的是整个指针的大小,单位是字节

	printf("%d\n", sizeof(*(a[0] + 1)));
	//结果:4字节
	//解释:a[0]表示二维数组的第一行,,第一行是一个有四个元素的一维数组,在二维数组中a[0]就相当于一维数组名,并不是单独放在二维数组中,所以他就是一维数组首元素地址,地址就是指针,
	//     指针类型是int*,a[0]+1就是跳过一个int大小,得到a[0][1]的地址,地址就是指针,拿到a[0][1]这个元素,元素类型是int类型,所以sizeof(*(a[0]+1))=sizeof(int),单位是字节

	printf("%d\n", sizeof(a + 1));
	//结果:4/8字节
	//解释:a是数组名,并没有单独放在sizeof内部,所以a是二维数组首行地址,地址就是指针,类型是int (*arr)[4],a+1跳过一个有4个int类型元素的数组,得到a[1],
	//     也就是二维数组第二行地址,地址就是指针,所以sizeof(a+1)计算的是指针大小

	printf("%d\n", sizeof(*(a + 1)));
	//结果:16字节
	//解释:a是数组名,并没有单独放在sizeof内部,所以a是二维数组首行地址,地址就是指针,类型是int (*arr)[4],a+1跳过一个有4个int类型元素的数组,得到a[1],
	//     也就是二维数组第二行地址,对其解引用得到的是二维数组中第二行一维数组,sizeof(*(a+1))=sizeof(a[1])=4*4=16,单位是字节

	printf("%d\n", sizeof(&a[0] + 1));
	//结果:4/8字节
	//解释:a[0]表示二维数组的第一行,,第一行是一个有四个元素的一维数组,&a[0]得到的是二维数组的第一行整个数组的地址,地址就是指针,指针类型是int (*arr)[4],&a[0]+1跳过一个一维数组的大小,
	//     得到的就是二维数组中第二行整个一维数组的地址,地址就是指针,所以sizeof(&a[0]+1)计算的就是指针的大小

	printf("%d\n", sizeof(*(&a[0] + 1)));
	//结果:16字节
	//解释:a[0]表示二维数组的第一行,,第一行是一个有四个元素的一维数组,&a[0]得到的是二维数组的第一行整个数组的地址,地址就是指针,指针类型是int (*arr)[4],&a[0]+1跳过一个一维数组的大小,
	//     得到的就是二维数组中第二行整个一维数组的地址,*(&a[0]+1)得到的就是二维数组中的第二行一维数组,sizeof(*(&a[0] + 1))=sizeof(a[1])=4*4=16,单位是字节

	printf("%d\n", sizeof(*a));
	//结果:16字节
	//解释:a是二维数组的数组名,数组名不没有单独放在sizeof内部,所以a是第一行的地址,地址就是指针,指针类型是int (*arr)[4],
	//     *a得到的就是二维数组中的整个第一行一维数组,sizeof(*a)=sizeof(a[0])=4*4=16,单位是字节

	printf("%d\n", sizeof(a[3]));
	//结果:	16字节
	//解释:a[3]在二维数组中就相当于拿到下标为3的一整行一维数组,a[3]也就是第四行的一维数组名,数组名在sizeof内部,计算的是整个数组的大小,
	//     虽然没有数组没有第四行,但是可以给a[3]预分配一个空间,所以给a[3]预分配一个int [4]的空间,sizeof计算的只是类型的大小,这里a[3]的类型就是int [4],所以sizeof(a[3])=4*4=16,单位是字节

	return 0;
}

3.3 输出结果

3.3.1 32位平台

3.3.2 64位平台

4. 例题4.指针

4.1 例题

#include <stdio.h>
int main()
{
	int a[5] = { 1, 2, 3, 4, 5 };
	int* ptr = (int*)(&a + 1);
	printf("%d,%d", *(a + 1), *(ptr - 1));
	return 0;
}

4.2 解析

5. 例题5.指针

5.1 例题

struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
	p = (struct Test*)0x100000;
	printf("%p\n", p + 0x1);
	printf("%p\n", (unsigned long)p + 0x1);
	printf("%p\n", (unsigned int*)p + 0x1);
	return 0;
}

5.2 解析

6. 例题6.指针

6.1 例题

#include <stdio.h>
int main()
{
	int a[4] = { 1, 2, 3, 4 };
	int* ptr1 = (int*)(&a + 1);
	int* ptr2 = (int*)((int)a + 1);
	printf("%x,%x", ptr1[-1], *ptr2);
	return 0;
}

6.2 解析

7. 例题7.指针

7.1 例题

#include <stdio.h>
int main()
{
	int a[3][2] = { (0, 1), (2, 3), (4, 5) };
	int* p;
	p = a[0];
	printf("%d", p[0]);
	return 0;
}

7.2 解析

8. 例题8.指针

8.1 例题

#include <stdio.h>
int main()
{
	int a[5][5];
	int(*p)[4];
	p = a;
	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
	return 0;
}

8.2 解析

9. 例题9.指针

9.1 例题

#include <stdio.h>
int main()
{
	int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int* ptr1 = (int*)(&aa + 1);
	int* ptr2 = (int*)(*(aa + 1));
	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
	return 0;
}

9.2 解析

10. 例题10.指针

10.1 例题

#include <stdio.h>
int main()
{
	char* a[] = { "work","at","alibaba" };
	char** pa = a;
	pa++;
	printf("%s\n", *pa);
	return 0;
}

10.2 解析

11. 例题11.指针

11.1 例题

#include <stdio.h>
int main()
{
	char* c[] = { "ENTER","NEW","POINT","FIRST" };
	char** cp[] = { c + 3,c + 2,c + 1,c };
	char*** cpp = cp;
	printf("%s\n", **++cpp);
	printf("%s\n", *-- * ++cpp + 3);
	printf("%s\n", *cpp[-2] + 3);
	printf("%s\n", cpp[-1][-1] + 1);
	return 0;
}

11.2 解析

![](https://img-blog.csdnimg.cn/img_convert/24baf958d698b0ac8197755d5762942d.png

12. 总结

  1. sizeof计算大小的时候,首先关心计算对象,是一个变量还是一个数组名,还是什么,这里重点放在计算数组上,如果sizeof内部包含一个单独的数组名,说明这个sizeof计算的是整个数组的大小,否则不是,单位是字节,这个很重要,假如说sizeof(arr[2][2]),这个二维数组的类型是int,那么这个sizeof(arr[2][2])= 224=16,单位是字节。计算字符串数组的时候,sizeof(arr)计算包含’\0’的计算,'\0’也是占空间。
  2. strlen计算的是’\0’之前的元素个数,在数组中,数组中不包含’\0’的话,一般这里就是随机值,另外注意strlen库函数再求一个字符解引用的时候会出现报错,原因就是非法访问。
  3. &数组名,取的是整个数组的地址,&arr+1也是跳过整个数组的大小
  4. 对指针进行解引用的时候,要关注指针对应的元素类型,这决定了拿取多少个字节的空间,指针±操作的时候要关注类型,决定步长。
  • 13
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

脚踏车(crush)

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

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

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

打赏作者

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

抵扣说明:

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

余额充值