各位CSDN的uu们你们好呀,今天小雅兰的内容还是我们的指针呀,上两篇博客我们基本上已经把知识点过了一遍,这篇博客就让小雅兰来带大家看一些和指针有关的题目吧,现在,就让我们进入指针的世界吧
复习:
数组和指针
数组——能够存放一组相同类型的元素,数组的大小取决于数组的元素个数和元素类型
指针——地址/指针变量,大小是4or8个字节
数组是数组,指针是指针,二者不等价
数组名是数组首元素的地址,这个地址就可以存放在指针变量中
可以使用指针来遍历数组
数组名
大部分情况下数组名是数组首元素的地址
但是有两个例外:
sizeof(数组名)——数组名表示整个数组,计算的是整个数组的大小
&数组名——数组名表示整个数组,取出的是数组的地址
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> 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)); }
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));//16
//sizeof(a)就是数组名单独放在sizeof内部,计算的是数组的总大小,单位是字节
printf("%d\n", sizeof(a + 0));//4or8个字节
//a+0 其实是数组首元素的地址
printf("%d\n", sizeof(*a));//4
//a是数组首元素的地址——&a[0]
//*a-*&a[0]-a[0]
//那么就是一个整形元素的大小,就是4个字节
printf("%d\n", sizeof(a + 1));//4or8
//a是数组首元素的地址-&a[0] int *
//a+1 表示跳过一个整型,是第二个元素的地址
printf("%d\n", sizeof(a[1]));//4
//数组第二个元素
printf("%d\n", sizeof(&a));//4or8
//&a-取出的是数组的地址,但是数组的地址也是地址啊,是地址,大小就是4or8个字节
//int (*pa)[4]=&a;——数组指针
printf("%d\n", sizeof(*&a));//16
//*操作符和&操作符互相抵消,结果就是sizeof(a)
printf("%d\n", sizeof(&a + 1));//4or8
//&a-取出整个数组的地址 int (*)[4]
//&a+1-跳过一个数组
printf("%d\n", sizeof(&a[0]));//4or8
//取出首元素的地址
printf("%d\n", sizeof(&a[0] + 1));//4or8
//第二个元素的地址
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.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)); return 0; }
sizeof计算的是占用内存空间的大小,单位是字节,不关注内存中到底存放的是什么
sizeof不是函数,是操作符
strlen是函数
strlen是针对字符串的,求的是字符串的长度,本质上统计的是\0之前出现的字符
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));//6
//数组的总大小
printf("%d\n", sizeof(arr + 0));//4or8
//数组名是首元素的地址
//arr+0 表示数组首元素的地址
printf("%d\n", sizeof(*arr));//1
//数组名表示数组首元素的地址-&arr[0]
//*arr就是数组的第一个元素,就是求首元素的大小
printf("%d\n", sizeof(arr[1]));//1
//数组的第二个元素
printf("%d\n", sizeof(&arr));//4or8
//&arr取出的是整个数组的地址
printf("%d\n", sizeof(&arr + 1));//4or8
//&arr+1-跳过一个数组
printf("%d\n", sizeof(&arr[0] + 1));//4or8
//数组第二个元素的地址
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<string.h> int main() { //字符数组 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)); return 0; }
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));//随机值
printf("%d\n", strlen(arr + 0));//随机值
printf("%d\n", strlen(*arr));//err
//*arr就表示字符a,字符a的ASCII码值是97
//就是说,把内存为97的地址访问了,这是一个非法访问
printf("%d\n", strlen(arr[1]));//err
//字符b的ASCII码值为98,把98当成了地址
//又非法访问了
printf("%d\n", strlen(&arr));//随机值
//取出的是整个数组的地址
printf("%d\n", strlen(&arr + 1));//随机值
//&arr+1-跳过一个数组
//这个随机值和上面的随机值比起来,应该是:随机值-6
printf("%d\n", strlen(&arr[0] + 1));//随机值
//从字符b往后数,还是一个随机值
//这个随机值和上面的随机值比起来,应该是:随机值-1
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int main() { char arr[] = "abcdef";//a b c d e f \0 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)); return 0; }
char arr[] = "abcdef";
//a b c d e f \0
printf("%d\n", sizeof(arr));//7
//计算的是数组总元素的大小,\0也算
printf("%d\n", sizeof(arr + 0));//4or8
//计算的是数组首元素的地址
printf("%d\n", sizeof(*arr));//1
//*arr就是数组首元素,计算的是第一个元素的大小
//arr[0]——*(arr+0)
//求元素个数
//int sz=sizeof(arr)/sizeof(arr[0]);
//int sz=sizeof(arr)/sizeof(*arr);
printf("%d\n", sizeof(arr[1]));//1
//计算的是数组第二个元素的大小
printf("%d\n", sizeof(&arr));//4or8
//取出的是整个数组的地址,是地址就是4个或者8个字节
printf("%d\n", sizeof(&arr + 1));//4or8
//跳过一个数组,但还是地址
printf("%d\n", sizeof(&arr[0] + 1));//4or8
//数组第二个元素的地址
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<string.h> int main() { 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)); return 0; }
char arr[] = "abcdef";
//a b c d e f \0
printf("%d\n", strlen(arr));//6
//找\0
printf("%d\n", strlen(arr + 0));//6
printf("%d\n", strlen(*arr));//err
//求的是数组首元素,把首元素当成了地址,形成了非法访问
printf("%d\n", strlen(arr[1]));//err
//求的是数组第二个元素
printf("%d\n", strlen(&arr));//6
//&arr-char (*)[7]
//也是数到\0就停止了
printf("%d\n", strlen(&arr + 1));//随机值
printf("%d\n", strlen(&arr[0] + 1));//5
//从数组第二个元素开始数,数到\0
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.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)); return 0; }
char* p = "abcdef";
//把首字符a的地址放在p变量中,p是一个指针变量
printf("%d\n", sizeof(p));//4or8
//计算的是指针变量的大小,也就是计算a的地址的大小
printf("%d\n", sizeof(p + 1));//4or8
//计算的是字符b的地址的大小
printf("%d\n", sizeof(*p));//1
//p是一个指针变量,里面存放的是a的地址
//p解引用之后就是元素a,字符a的大小是一个字节
printf("%d\n", sizeof(p[0]));//1
//可以把p[0]理解为*(p+0)
//也就是字符a,字符a的大小是1个字节
printf("%d\n", sizeof(&p));//4or8
//取出的是p的地址
printf("%d\n", sizeof(&p + 1));//4or8
//p-char *
//&p-char **
//char * p;
//char * *pp=&p;
//&p+1跳过一个char*的元素
//反正还是地址
printf("%d\n", sizeof(&p[0] + 1));//4or8
//第二个元素的地址
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<string.h> int main() { 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)); return 0; }
char* p = "abcdef";
printf("%d\n", strlen(p));//6
//p是a的地址
printf("%d\n", strlen(p + 1));//5
//p+1是b的地址
printf("%d\n", strlen(*p));//err
//字符a 非法访问了
printf("%d\n", strlen(p[0]));//err
//字符a 非法访问了
printf("%d\n", strlen(&p));//随机值
//a的地址的地址,什么时候遇到\0完全是不可知的
printf("%d\n", strlen(&p + 1));//随机值
//跳过p变量
//这两个随机值是没有关系的
printf("%d\n", strlen(&p[0] + 1));//5
//从字符b往后数,数到\0
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<string.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; }
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));//48——3*4*4
//a这个二维数组的数组名单独放在sizeof内部,计算的是二维数组的总大小
printf("%d\n", sizeof(a[0][0]));//4
//第一行第一个元素
printf("%d\n", sizeof(a[0]));//16
//a[0]是第一行的数组名,这时数组名单独放在sizeof内部了
//计算的是数组的大小,单位是字节
//计算的是第一行的大小
printf("%d\n", sizeof(a[0] + 1));//4or8
//a[0]不是单独放在sizeof内部,a[0]表示首元素的地址
//也就是第一行第一个元素的地址,即&a[0][0]
//那么,a[0]+1就是第一行第二个元素的地址,也就是&a[0][1]
printf("%d\n", sizeof(*(a[0] + 1)));//4
//第一行第二个元素
printf("%d\n", sizeof(a + 1));//4or8
//a作为二维数组的数组名并非单独放在sizeof内部,所以表示首元素的地址
//二维数组的首元素是第一行,这里的a就是第一行的地址——int (*)[4]
//a+1是跳过第一行,指向了第二行
//所以是第二行的地址
printf("%d\n", sizeof(*(a + 1)));//16
//第二行的元素得大小 4*4
//*(a+1)——a[1]
printf("%d\n", sizeof(&a[0] + 1));//4or8
//取出第一行的地址,&a[0]+1是第二行的地址
printf("%d\n", sizeof(*(&a[0] + 1)));//16
//第二行的元素的大小
printf("%d\n", sizeof(*a));//16
//*a 数组名表示首元素的地址,a就表示二维数组第一行的地址
//解引用就是第一行的元素
printf("%d\n", sizeof(a[3]));//16
//第四行的数组名
//不存在越界
//因为,sizeof内部的表达式不会真的计算
//所以,编译器压根不会去访问第四行,而是直接根据类型属性判断
好啦,小雅兰今天的内容就到这里啦,指针系列的博客真的花了小雅兰超级多的时间,未来还要继续加油呀!!!