【C语言进阶】
文章目录
九、指针和数组笔试题详细解析
1 一维数组
示例:
#include<stdio.h>
int main()
{
//一维数组
int arr[] = { 1,2,3,4 };
printf("%d\n", sizeof(arr));
//sizeof(arr)表示整个数组的大小:4*4=16
printf("%d\n", sizeof(arr + 0));
//arr+0表示数组首元素的地址,地址的大小:4/8
printf("%d\n", sizeof(*arr));
//arr表示数组首元素的地址,*arr表示数组首元素,int型数据的大小:4
printf("%d\n", sizeof(arr + 1));
//arr+1表示数组下标为1的元素的地址(第二个元素的地址),地址的大小:4/8
printf("%d\n", sizeof(arr[1]));
//arr[1]表示数组下标为1的元素(第二个元素),int型数据的大小:4
printf("%d\n", sizeof(&arr));
//&arr表示整个数组的地址,地址的大小:4/8
printf("%d\n", sizeof(*&arr));
//*&arr表示数组名:arr;sizeof(arr)表示整个数组的大小:16
printf("%d\n", sizeof(&arr + 1));
//&arr+1表示向后跳过一个数组类型大小的地址,地址的大小:4/8
printf("%d\n", sizeof(&arr[0]));
//&arr[0]表示数组首元素的地址,地址的大小:4/8
printf("%d\n", sizeof(&arr[0] + 1));
//&arr[0]+1表示下标为1元素的地址(第二个元素的地址),地址的大小:4/8
/*
* x86 x64
* 16 16
* 4 8
* 4 4
* 4 8
* 4 4
* 4 8
* 16 16
* 4 8
* 4 8
* 4 8
*/
return 0;
}
2 字符数组
2.1 用初始化列表初始化的字符数组
示例:
#include<stdio.h>
#include<string.h>
int main()
{
//字符数组 - 用初始化列表(字符)初始化的字符数组
char ch[] = { 'a','b','c','d','e','f' };//a b c d e f
//siezof:以字节为单位计算对象的大小
printf("%d\n", sizeof(ch));
//sizeof(ch)表示整个数组的大小:1*6=6
printf("%d\n", sizeof(ch + 0));
//ch+0表示数组首元素的地址,地址的大小:4/8
printf("%d\n", sizeof(*ch));
//*ch表示数组首元素,char型数据的大小:1
printf("%d\n", sizeof(ch[1]));
//ch[1]表示数组下标为1的元素(第二个元素),char型数据的大小:1
printf("%d\n", sizeof(&ch));
//&ch表示整个数组的地址,地址的大小:4/8
printf("%d\n", sizeof(&ch + 1));
//&ch+1表示向后跳过一个数组类型大小的地址,地址的大小:4/8
printf("%d\n", sizeof(&ch[0] + 1));
//&ch[0]+1表示数组下标为1元素的地址(第二个元素的地址),地址的大小:4/8
printf("\n");
/*
* x86 x64
* 6 6
* 4 8
* 1 1
* 1 1
* 4 8
* 4 8
* 4 8
*/
//strlen:求字符串长度的库函数,统计的是字符串中'\0'(不包括)之前的字符个数;
//如果没有'\0',会越过字符数组向后一直寻找,直到遇到'\0'
//strlen的参数为地址
printf("%d\n", strlen(ch));
//ch表示数组首元素的地址,该字符数组中没有'\0',strlen会越过数组向后继续寻找,直到遇见'\0'
//最后统计的字符数是:随机值
printf("%d\n", strlen(ch + 0));
//ch+0表示数组首元素的地址,该字符数组中没有'\0',strlen会越过数组向后继续寻找,直到遇见'\0'
//最后统计的字符数是:随机值
printf("%d\n", strlen(*ch));//error
//*ch表示数组首元素'a',字符'a'的ASCII码值为97,将97作为地址访问,向后统计字符个数
//error,非法访问内存地址
printf("%d\n", strlen(ch[1]));//error
//ch[1]表示啊数组首元素'a',字符'a'的ASCII码值为97,将97作为地址访问,向后统计字符个数
//error,非法访问内存地址
printf("%d\n", strlen(&ch));
//&ch表示整个数组的地址,与数组首元素地址的值相同,传递给strlen依然是从数组首元素的地址处向后找'\0
//最后统计的字符数是:随机值
printf("%d\n", strlen(&ch + 1));
//&ch+1表示向后跳过一个数组类型大小的地址,与传递&ch和ch所计算的大小差一个数组长度(6)
//最后统计的字符数是:随机值
printf("%d\n", strlen(&ch[0] + 1));
//&ch[0]+1表示第二个元素的地址,与传递&ch和ch所计算的大小差1
//最后统计的字符数是:随机值
return 0;
}
2.2 用字符串初始化的字符数组
示例:
#include<stdio.h>
#include<string.h>
int main()
{
//字符数组 - 用字符串初始化的字符数组
char ch[] = "abcdef";//a b c d e f \0
//siezof:以字节为单位计算对象的大小
printf("%d\n", sizeof(ch));
//整个数组的大小:1*7=7
printf("%d\n", sizeof(ch + 0));
//首元素地址的大小:4/8
printf("%d\n", sizeof(*ch));
//数组首元素的大小:1
printf("%d\n", sizeof(ch[1]));
//数组第二个元素的大小:1
printf("%d\n", sizeof(&ch));
//数组类型的地址:4/8
printf("%d\n", sizeof(&ch + 1));
//数组类型的地址:4/8
printf("%d\n", sizeof(&ch[0] + 1));
//数组第二个元素的地址:4/8
printf("\n");
/*
* x86 x64
* 7 8
* 4 8
* 1 1
* 1 1
* 4 8
* 4 8
* 4 8
*/
//strlen:求字符串长度的库函数,统计的是字符串中'\0'(不包括)之前的字符个数;
//如果没有'\0',会越过字符数组向后一直寻找,直到遇到'\0'
//strlen的参数为地址
printf("%d\n", strlen(ch));
//<6> -- 从首元素的地址处向后找\0
printf("%d\n", strlen(ch + 0));
//<6> -- 从首元素的地址处向后找\0
printf("%d\n", strlen(*ch));//error
//<非法访问>
printf("%d\n", strlen(ch[1]));//error
//<非法访问>
printf("%d\n", strlen(&ch));
//<6> -- 从首元素的地址处向后找\0
printf("%d\n", strlen(&ch + 1));
//<随机值> -- 从'\0'(数组末尾元素)之后的位置开始找\0
printf("%d\n", strlen(&ch[0] + 1));
//<5> -- 从第2个元素的地址处向后找\0
/*
* 6
* 6
* 6
* 随机值
* 5
*/
return 0;
}
2.3 指向常量字符串的字符指针
示例:
#include<stdio.h>
#include<string.h>
int main()
{
//字符数组 - 指向常量字符串的字符指针
char* p = "abcdef";//字符指针p指向常量字符串,指针变量存放的是首字符'a'的地址
//siezof:以字节为单位计算对象的大小
printf("%d\n", sizeof(p));
//p的值是'a'的地址,地址的大小:4/8
printf("%d\n", sizeof(p + 1));
//p+1表示'b'的地址,地址的大小:4/8
printf("%d\n", sizeof(*p));
//*p表示字符'a',一个char型数据的大小:1
printf("%d\n", sizeof(p[0]));;
//p[0]表示字符'a',一个char型数据的大小:1
printf("%d\n", sizeof(&p));
//指针变量p的地址,地址的大小:4/8
printf("%d\n", sizeof(&p + 1));
//&p+1是指针变量p之后位置的地址,地址的大小:4/8
printf("%d\n", sizeof(&p[0] + 1));
//&p[0]+1表示字符'b'的地址,地址的大小:4/8
printf("\n");
/*
* x86 x64
* 4 8
* 4 8
* 1 1
* 1 1
* 4 8
* 4 8
* 4 8
*/
//strlen:求字符串长度的库函数,统计的是字符串中'\0'(不包括)之前的字符个数;
//strlen的参数为地址
//要明确strlen从何地址处开始向后找\0
printf("%d\n", strlen(p));
// <6>-- 从首元素的地址处向后找\0
printf("%d\n", strlen(p + 1));
// <5> -- 从第二个元素的地址处向后找\0
printf("%d\n", strlen(*p));//error
// <非法访问>
//printf("%d\n", strlen(p[0]));//error
// <非法访问>
printf("%d\n", strlen(&p));
// 随机值 -- 从指针变量的地址处向后找\0
printf("%d\n", strlen(&p + 1));
// 随机值 -- 从指针变量后一个类型大小的地址处向后找\0
printf("%d\n", strlen(&p[0] + 1));
// <5> -- 从第二个元素开始向后找\0
/*
* 6
* 5
* 随机值
* 随机值
* 5
*/
return 0;
}
3 二维数组
示例:
#include<stdio.h>
int main()
{
//二维数组
int arr[3][4] = { 0 };
printf("%d\n", sizeof(arr));
//整个二维数组的大小(int[3][4]):3*4*4=48
printf("%d\n", sizeof(arr[0][0]));
//二维数组首元素(一维数组)的首元素,即第一行第一列元素的大小(int):4
printf("%d\n", sizeof(arr[0]));
//二维数组首元素(第一行、一维数组的数组名)的大小(int[4]):4*4=16
printf("%d\n", sizeof(arr[0] + 1));
//arr[0]表示二维数组首元素(一维数组数组名),+1表示第1行第2个元素的地址,地址的大小:4/8
printf("\n");
/*
* x86 x64
* 48 48
* 4 4
* 16 16
* 4 8
*/
printf("%d\n", sizeof(*(arr[0] + 1)));
//第一行第二个元素(arr[0][1])的大小(int):4
printf("%d\n", sizeof(arr + 1));
//arr表示二维数组名,是二维数组首元素arr[0]的地址;
//arr+1表示二维数组第二个元素的地址(&arr[1]):4/8
printf("%d\n", sizeof(*(arr + 1)));
//*(arr+1)相当于*&arr[1],arr[1]表示二维数组第二个元素,是一个数组名;
//sizeof(数组名)计算的是整个数组的大小(int[4]):4*4=16
printf("%d\n", sizeof(&arr[0] + 1));
//&arr[0]表示二维数组首元素的地址(一维数组的地址)
//+1表示向后跳过一个数组类型的大小(int*[4]),地址的大小:4/8
printf("%d\n", sizeof(*(&arr[0] + 1)));
//对一个数组类型解引用,获得的是整个一维数组;
//*(&arr[0]+1)相当于arr[1],相当于二维数组第二个元素(一维数组数组名)
//整个一维数组的大小(int[4]):4*4=16
printf("%d\n", sizeof(*arr));
//*arr表示二维数组首元素,即一个一维数组的大小(int[4]):4*4=16
printf("%d\n", sizeof(arr[3]));
//一个一维数组数组名,表示整个一维数组的大小(int[4]):4*4=16
/*
* x86 x64
* 4 4
* 4 8
* 16 16
* 4 8
* 16 16
* 16 16
* 16 16
*/
return 0;
}
4 数组名的意义
1.sizeof(数组名)
:计算的是整个数组的大小,或者说是计算一个数组类型的大小。
2.&数组名
:取出的是整个数组的地址,或者说是一个数组类型的地址。
3.其他地方的数组名都表示首元素的地址。
5 再探 sizeof
操作符
sizeof()
只会的分析括号内对象的类型,然后给出大小,不会实际访问内存去计算。
代码示例:
#include<stdio.h>
int main()
{
//再探sizeof操作符
int a = 3;
short b = 4;
//sizeof在编译期间就获取了对象的大小,
//不会在程序运行期间实际访问内存去计算
printf("%d\n", sizeof(b = a + 2));//2
printf("%d\n", sizeof(b));//2
return 0;
}
解释说明:
1 sizeof
在编译期间就获取了对象的大小。
注意:表达式的2个属性
1.值属性: 表达式都会有一个结果值
2.类型属性: b = a + 2
-> short
总结:
本节给出了指针与数组相关笔试题的实例和解析,对指针与数组有了更加深入的理解。
感谢您的阅读!如有任何错误,欢迎您的批评指正!