> 文章列表 > 深度剖析指针(下)——“C”

深度剖析指针(下)——“C”

深度剖析指针(下)——“C”

各位CSDN的uu们你们好呀,今天小雅兰的内容还是我们的指针呀,上两篇博客我们基本上已经把知识点过了一遍,这篇博客就让小雅兰来带大家看一些和指针有关的题目吧,现在,就让我们进入指针的世界吧

复习:

数组和指针

数组——能够存放一组相同类型的元素,数组的大小取决于数组的元素个数和元素类型

指针——地址/指针变量,大小是4or8个字节

数组是数组,指针是指针,二者不等价

数组名是数组首元素的地址,这个地址就可以存放在指针变量中

可以使用指针来遍历数组 

数组名

大部分情况下数组名是数组首元素的地址

但是有两个例外:

  1. sizeof(数组名)——数组名表示整个数组,计算的是整个数组的大小
  2. &数组名——数组名表示整个数组,取出的是数组的地址 
#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 \\0printf("%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内部的表达式不会真的计算
    //所以,编译器压根不会去访问第四行,而是直接根据类型属性判断

 

 


好啦,小雅兰今天的内容就到这里啦,指针系列的博客真的花了小雅兰超级多的时间,未来还要继续加油呀!!!