在上节的内容中,我们进一步学习了有关指针
的内容,并做了一些关于指针的题目,今天我们将继续练习一些指针的题目,以便大家更好的理解和掌握指针的知识,好了,话不多说,开整!!!
字符数组指针练习题(二)
在第一节的内容中,我们已经练习了字符数组
的相关题目,当然了,我们当时是使用如下方式定义数组的:
char arr[] = {'a','b','b'};
在C语言学习(十一)讲的时候,我们不仅学习了字符数组
的这种定义方式,同样还有另外一种定义方式,如下:
char arr[] = "abb";
并且两者有着一些区别,因此,有必要练习相应的题目。
sizeof题目
首先我们分析sizeof
题目,代码如下所示:
#include<stdio.h>
int main()
{
char arr[] = "abvctr";
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[1]));
printf("%d\n",sizeof(&arr));
printf("%d\n",sizeof(*&arr));
printf("%d\n",sizeof(&arr+1));
printf("%d\n",sizeof(*&arr[0]));
printf("%d\n",sizeof(&arr[0]+1));
return 0;
}
在自行分析完毕后,再查看以下分析讲解:
#include<stdio.h>
int main()
{
char arr[] = "abvctr";//此定义方式会 自动补充字符串结束标志\0
printf("%d\n",sizeof(arr));//数组名默认为首元素地址,但两种情况除外,一个就是单独在sizeof内部,另一个就是&arr
//特殊情况其代表了整个数组,一个字符一个字节,因此一共6+1=7个字节 \0也占一个字节
printf("%d\n",sizeof(arr+0));//数组名默认为首元素地址,加0仍为首元素a的地址,地址则为4字节(32位)
printf("%d\n",sizeof(*arr));//数组名默认为首元素地址,对其解引用,则为字符a,大小为1字节
printf("%d\n",sizeof(arr+1));//首元素地址加1为数组中b的地址,地址则为4字节(32位)
printf("%d\n",sizeof(arr[1]));//数组中第二个元素b的大小,字符类型,故1字节
printf("%d\n",sizeof(&arr));//特殊情况2:此时数组名代表整个数组,&arr:取出整个数组的地址,地址则为4字节(32位)
printf("%d\n",sizeof(*&arr));//整个数组解引用,故7字节
printf("%d\n",sizeof(&arr+1));//整个数组的地址,加1仍是一个地址,地址则为4字节(32位)
printf("%d\n",sizeof(*&arr[0]));//取出第一个元素的地址并解引用,则为字符a其大小为1字节
printf("%d\n",sizeof(&arr[0]+1));取出第一个元素的地址,再加1为第二个元素b的地址,地址则为4字节(32位)
return 0;
}
我们编译查看结果,结果如下:
由此可见,分析正确。
strlen题目
下面请分析以下代码:
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = "abvctr";//此定义方式会 自动补充字符串结束标志\0
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[1]));
printf("%d\n",strlen(&arr));
printf("%d\n",strlen(&arr+1));
printf("%d\n",strlen(&arr[0]+1));
return 0;
}
在分析结束后,再查看以下的参考分析:
#include<stdio.h>
#include<string.h>
int main()
{
char arr[] = "abvctr";//此定义方式会 自动补充字符串结束标志\0
//strlen:计算\0之前的字符的个数
printf("%d\n",strlen(arr));//arr默认首元素地址,从该地址向后寻找 \0 因此,值为6
printf("%d\n",strlen(arr+0));//arr默认首元素地址,加0还是首元素地址,从该地址向后寻找
// \0 因此,值仍为6
printf("%d\n",strlen(*arr));//arr默认首元素地址,对其解引用则为数组中的字符a,因此,将会以a对应的ASCII码值97
// 作为开始,向后寻找\0,因此会报错
printf("%d\n",strlen(arr+1));//arr默认首元素地址,加1则变为第二个元素的地址,从该地址向后寻找\0,因此结果为5
printf("%d\n",strlen(arr[1]));//arr[1]代表字符b,因此,将会以b对应的ASCII码值98
// 作为开始,向后寻找\0,因此会报错
printf("%d\n",strlen(&arr));//&arr,即取到整个数组的地址,从该地址向后寻找\0,结果仍为6
printf("%d\n",strlen(&arr+1));//从整个数组的最后一个元素指向的地址的下一个地址开始寻找\0,因此其为随机值
printf("%d\n",strlen(&arr[0]+1));//arr[0]即首元素地址,再加1变为了第二个元素的地址,从该地址向后寻找\0,值为6-1=5
return 0;
}
我们编译运行,结果如下:
可以看到程序中断了,我们在Linux
下可以更清楚地看到错误,如下图:
我们将分析的两行错误代码进行注释,再编译运行:
可以看到,结果与我们分析的一致,以上便是字符数组的指针练习题。
常量字符串
在C语言学习(十九)时,我们学习了const修饰指针
,大家忘了的话可以自行查看,那么如果我们使用const对字符指针变量进行修饰,并将一串字符赋值给该指针,就定义了常量字符串
,内容不可更改,如下代码所示:
const char* p = "abvctr";
此时字符指针p指向的时字符数组abvctr
中a所在位置的地址上,下面验证:
我们对p解引用并打印
,可以看到其为字符a
在了解了常量字符串
之后,我们再练习以下两题:
sizeof题目
请分析以下代码:
#include<stdio.h>
int main()
{
const char* p = "abvctr";
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));
return 0;
}
在自行分析后,再查看以下内容:
#include<stdio.h>
int main()
{
const char* p = "abvctr";
printf("%d\n",sizeof(p));//p为指向字符数组中的a的指针,也即其地址,地址则为4字节
printf("%d\n",sizeof(p+1));//p为指向字符数组中的a的指针,加1则指向b,仍为地址,4字节(32位)
printf("%d\n",sizeof(*p));//对p解引用,则位字符a,1字节
printf("%d\n",sizeof(p[0]));//p[0]代表字符a,字符占1字节
printf("%d\n",sizeof(&p));//取出p的地址,地址则为4字节(32位)
printf("%d\n",sizeof(&p+1));//p为首元素a的地址,&p:取出a的地址,再加1,则变为指向字符b的地址,4字节
printf("%d\n",sizeof(&p[0]+1));//同上,4字节
return 0;
}
编译运行结果,可以看到和我们分析的一样:
strlen题目
请看以下代码并分析结果:
#include<stdio.h>
#include<string.h>
int main()
{
const char* p = "abvctr";
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;
}
在分析完后,再查看以下分析:
#include<stdio.h>
#include<string.h>
int main()
{
const char* p = "abvctr";
printf("%d\n",strlen(p));//从p指向的地址开始,向下寻找\0,因此值为6
printf("%d\n",strlen(p+1));//p+1:从p开始的下一个地址开始寻找\0,因此值为5
printf("%d\n",strlen(*p));//对p解引用,则为字符a,以字符a对应的ASCII码值97作为地址,向下寻找\0,将会报错
printf("%d\n",strlen(p[0]));//p[0]代表字符a,以字符a对应的ASCII码值97作为地址,向下寻找\0,将会报错
printf("%d\n",strlen(&p));//&p代表整个常量字符串的地址,从此地址开始向下找\0,结果为随机值
printf("%d\n",strlen(&p+1));//从常量字符串结束地址的下一个地址开始,向下寻找\0,将会是随机值
printf("%d\n",strlen(&p[0]+1));//p[0]代表字符数组中的字符a,&p[0]代表取出该地址,再加1代表b的地址,
//从此地址开始向下找\0,值将为5
return 0;
}
在不注释错误代码的前提下编译运行,程序会崩溃,如下所示:
Linux
下可以更清楚的看到错误,如下图所示:
我们将错误代码注释,再次编译运行,可得以下结果:
可以发现,和我们的分析结果一致。
上述内容即使今天的全部内容了,感谢大家的观看。
如果方便,辛苦大家点个赞和关注哦!
您的点赞或评论或关注是对我最大的肯定,谢谢大家!!!