指针练习题
知识补充:
数组名的意义:
1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
2. & 数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
3. 除此之外所有的数组名都表示首元素的地址。
//一维数组
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));
解析:
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));//sizeof里面单独放置数组名a,此时a表示整个数组,结果为16
printf("%d\n", sizeof(a + 0));//这里的数组名a表示首元素的地址,a+0表示数组下标为0的元素的地址,
//即第一个元素的地址,而地址的大小就是4/8字节
printf("%d\n", sizeof(*a));//这里表示对数组首元素的地址进行解引用,得到的是整形数据1,结果为4
printf("%d\n", sizeof(a + 1));//这里的数组名a表示首元素的地址,a+1表示数组下标为1的元素的地址,
//即第二个元素的地址,而地址的大小就是4/8字节
printf("%d\n", sizeof(a[1]));//a[1]就是数组第二个元素,也就是整形数据,结果为4
printf("%d\n", sizeof(&a));//将&a放在sizeof内部,此时&a表示取出整个数组的地址,而地址的大小就是4/8个字节
printf("%d\n", sizeof(*&a));//&a将整个数组的地址拿出来,然后*对于&a进行解引用,*和&的作用相互抵消,
//相当于进行计算的是a,即sizeof(a),结果为16
printf("%d\n", sizeof(&a + 1));//&a取出的是整个数组的地址,&a+1就是跳过一个数组地址大小,而地址的大小就是4/8个字节
printf("%d\n", sizeof(&a[0]));//&a[0]就是取出数组元素a[0]的地址,是地址,大小就是4/8个字节
printf("%d\n", sizeof(&a[0] + 1));//&a[0]就是取出后数组元素a[0]的地址,
//而&a[0]+1就是在内存中跳过一个数组元素大小的字节数,但是性质依旧是地址,是地址大小就是4/8个字节
关于字符数组的题目分为好几种类型,下面分类为大家解答:
第一组
//字符数组
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));
解析:
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));//数组名arr表示的是整个数组的大小,结果为6
printf("%d\n", sizeof(arr + 0));//这里的arr表示数组首元素的地址,arr+0表示数组下标为0的元素的地址
//是地址,大小就是4/8个字节
printf("%d\n", sizeof(*arr));//数组名没有单独放在sozeof内部,则此时arr就是数组首元素的地址
//*arr就是得到首元素的值,也就是字符数据'a',此时结果为1
printf("%d\n", sizeof(arr[1]));//arr[1]就是数组下标为1的元素,也就是字符'b',结果为1
printf("%d\n", sizeof(&arr));//&arr取出的是整个数组的地址,是地址,结果就是4/8个字节
printf("%d\n", sizeof(&arr + 1));//同上,结果为4/8个字节
printf("%d\n", sizeof(&arr[0] + 1));//同上,结果为4/8个字节
第二组
char arr[] = { 'a','b','c','d','e','f' };
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));
解析:
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));//arr表示数组首元素的地址,而strlen函数计算的是\0之前的字符个数,
//该数组中的元素是没有存储\0的,而在后续的内存中,存储的\0的地址为随机放置,此处计算的值为随机值,>=6
printf("%d\n", strlen(arr + 0));//arr+0,即arr[0]处的地址,因此结果为随机值,>=6
printf("%d\n", strlen(*arr));//*arr,即字符'a'==97,而库函数strlen需要的值地址,
//此时该函数默认97为地址,但该地址为捏造的地址,不属于我们的操作范围,此时编译器会报错!
printf("%d\n", strlen(arr[1]));//结果同上
printf("%d\n", strlen(&arr));//&arr将整个数组的地址取出,而数组的地址和数组首元素的地址是一样的
//结果为随机值,>=6
printf("%d\n", strlen(&arr + 1));//此时strlen从数组arr后面一个地址处开始计数,结果为随机值,>=0
printf("%d\n", strlen(&arr[0] + 1));//结果同strlen(arr[1]);
第三组
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));
解析:
char arr[] = "abcdef";
该常量字符串在内存中存储的时候,结尾会自动放置一个\0
printf("%d\n", sizeof(arr));//arr表示整个数组的大小,结果为7(因为此处\0也要进行计算)
printf("%d\n", sizeof(arr + 0));//此时arr表示数组首元素的地址,arr+0表示arr[0]处的地址,
//是地址,大小就是4/8个字节
printf("%d\n", sizeof(*arr));//arr表示数组首元素的地址,*arr将该地址处的元素拿出,也就是arr[0],
//即sizeof(arr[0]);结果为1
printf("%d\n", sizeof(arr[1]));//理由同上,结果为1
printf("%d\n", sizeof(&arr));//&arr将整个数组的地址取出,是地址,大小就是4/8个字节
printf("%d\n", sizeof(&arr + 1));//理由同上,大小为4/8个字节
printf("%d\n", sizeof(&arr[0] + 1));//理由同上,大小为4/8个字节
第四组
char arr[] = "abcdef";
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));
解析:
char arr[] = "abcdef";
printf("%d\n", strlen(arr));//arr为数组首元素的地址,结果为6
printf("%d\n", strlen(arr + 0));//arr+0也就是arr[0]此处的地址,从arr[0]处开始计数,结果为6
printf("%d\n", strlen(*arr));//*arr将arr[0]处的元素拿出,也就是字符'a'==97,此时编译器报错
printf("%d\n", strlen(arr[1]));//理由同上,编译器报错
printf("%d\n", strlen(&arr));//数组的地址和数组首元素的地址相同,结果为6
printf("%d\n", strlen(&arr + 1));//此时strlen函数从arr数组后面开始计数,结果为随机值,>=0
printf("%d\n", strlen(&arr[0] + 1));//strlen函数从arr[1]处的地址向后计数,结果为5
第五组
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));
解析:
char* p = "abcdef";
printf("%d\n", sizeof(p));//指针p指向的是该常量字符串的首元素的地址,是地址,结果为4/8个字节
printf("%d\n", sizeof(p + 1));//指针p+1,指针指向的方向向后移动一位,即此时指向字符串第二个元素的地址,
//是地址,结果就是4/8个字节
printf("%d\n", sizeof(*p));//指针p指向的是字符串首元素的地址,*p对该地址解引用,拿到字符'a';结果为1
printf("%d\n", sizeof(p[0]));//p[0]也就是字符'a',结果为1
printf("%d\n", sizeof(&p));//p作为一个指针,本身也有一个存储的地址,而&p拿出的就是内存中用来存储p的地址,
//是地址,大小就是4/8个字节
printf("%d\n", sizeof(&p + 1));//&p+1,就是跳过一个指针地址的大小,来到指针p地址的后面一处的地址,
//是地址,大小就是4/8个字节
printf("%d\n", sizeof(&p[0] + 1));//理由同上,大小为4/8个字节
第六组
char* p = "abcdef";
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));
解析
printf("%d\n", strlen(p));//p指向的是该常量字符串首元素的地址,结果为6
printf("%d\n", strlen(p + 1));//此时p指向的是数组第二个元素的地址,结果为5
printf("%d\n", strlen(*p));//*p得到的是字符串的首元素,即字符'a'==97,此时编译器报错
printf("%d\n", strlen(p[0]));//理由同上,编译器报错
printf("%d\n", strlen(&p));//&p得到的是存储指针p的地址,计算结果为随机值,结果为>=0
printf("%d\n", strlen(&p + 1));//理由同上,结果为随机值
printf("%d\n", strlen(&p[0] + 1));//此时得到的是字符串第二个元素的地址,也就是从字符'b'开始计算
//结果为5
//二维数组
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]));
解析:
//二维数组
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));//a单独放在sizeof内部,此时表示整个数组,大小就是48个字节
printf("%d\n", sizeof(a[0][0]));//a[0][0]就是二维数组第一行第一个元素,该元素为整形元素,大小为4个字节
printf("%d\n", sizeof(a[0]));//a[0]表示第一行数组的数组名,表示的是该一维数组整个数组
//计算的是第一行整个数组的大小,大小为16
printf("%d\n", sizeof(a[0] + 1));//a[0]表示第一行数组的数组名,
//a[0]==&a[0][0]
//a[0]+1==&a[0][1]
//结果为4/8个字节
printf("%d\n", sizeof(*(a[0] + 1)));//a[0]+1==&a[0][1],*(a[0][1])==a[0][1],结果为4个字节
printf("%d\n", sizeof(a + 1));//数组名a表示首元素的地址,也就是第一行的一维数组的地址,a+1==&a[0]
//是地址,大小就是4/8个字节
printf("%d\n", sizeof(*(a + 1)));//*(a+1)==a[1],也就是sizeof(a[1]),计算的是第二行整个数组的大小,结果为16
printf("%d\n", sizeof(&a[0] + 1));//&a[0]+1==&a[1],是地址,大小就是4/8个字节
printf("%d\n", sizeof(*(&a[0] + 1)));//*(&a[1]),得到的是第二行一维数组,也就是sizeof(a[1]),结果为16
printf("%d\n", sizeof(*a));//a表示二维数组首元素的地址,即a[0],大小为16
printf("%d\n", sizeof(a[3]));//此处不会越界访问,得到的是第四行整个数组,大小为16个字节