• sizeof()与strlen()在指针和数组笔试题(超详细!!!绝对有帮助!!!)


    目录

    一、sizeof()

    二、strlen()

    三、指针和数组笔试题

    一、一维数组

    1.int a[] = {1,2,3,4};

    二、字符数组

    1、char arr[] = {'a','b','c','d','e','f'}

    2、char arr[] = "abcdef"

    3、char *p = "abcdef"

    三、二维数组

    1.int a[3][4] = { 0 };


     

    一、sizeof()

    sizeof 是计算对象或者类型创建的对象所占内存空间的大小,单位是字节,在计算字符串的空间大小时,包含了结束符\0的位置

    sizeof 是操作符,不是函数

    关于数组名:数组名是数组首元素的地址

    但是有2个例外:

    1. sizeof(数组名) - 数组名表示整个数组,计算的是整个数组的大小,单位是字节

    2. &数组名 - 数组名也表示整个数组,取出的是整个数组的地址,

    除了这个2个例外,你见到的所有的数组名都表示首元素的地址

    二、strlen()

    strlen 是库函数

    strlen 求字符串长度的,计算的是字符串中‘\0’之前出现的字符的个数统计到\0为止,如果没有看到‘\0’,会继续往后找。结束标志 ‘\0’ 是不被计算在长度当中的。

    三、指针和数组笔试题

    一、一维数组

    1.int a[] = {1,2,3,4};

    1. int a[] = {1,2,3,4};
    2. printf("%d\n",sizeof(a));
    3. printf("%d\n",sizeof(a+0));
    4. printf("%d\n",sizeof(*a));
    5. printf("%d\n",sizeof(a+1));
    6. printf("%d\n",sizeof(a[1]));
    7. printf("%d\n",sizeof(&a));
    8. printf("%d\n",sizeof(*&a));
    9. printf("%d\n",sizeof(&a+1));
    10. printf("%d\n",sizeof(&a[0]));
    11. printf("%d\n",sizeof(&a[0]+1));

    接下来我们来仔仔细细分析一下:

    分析第一个代码:

    printf("%d\n",sizeof(a));

    a作为数组名单独放在sizeof内部,计算的是数组的总大小,单位是字节

    则答案为  16

    分析第二个代码:

    printf("%d\n",sizeof(a+0));

    a并非单独放在sizeof内部也没有&,所以数组名a就是数组首元素的地址
    a+0还是数组首元素的地址,是地址大小就是 4/8 个字节

    则答案为  4(x86环境下)或者8(x64环境下)

    分析第三个代码:

    printf("%d\n",sizeof(*a));

    a是首元素的地址,*a就是首元素,sizeof(*a)就算的就是首元素的大小

    则答案为    4

    分析第四个代码:

    printf("%d\n",sizeof(a+1));

    a是首元素的地址,a+1是第二个元素的地址,sizeof(a+1)计算的是指针的大小 

    则答案为  4(x86环境下)或者8(x64环境下)

    分析第五个代码:

    printf("%d\n",sizeof(a[1]));

    a[1]就是数组的第二个元素,sizeof(a[1])的大小 —— 4个字节

    则答案为    4

    分析第六个代码:

    printf("%d\n",sizeof(&a));

    &a取出的数组的地址,数组的地址,也是地址呀,sizeof(&a)就是 4/8 个字节

    则答案为  4(x86环境下)或者8(x64环境下)

    在这里:

    a————>  int *(整型指针)     int* p = a;

    &a————> int (*)[4] (数组指针)     int (*pa)[4] = &a;

    a8eb464b18be4e04b8bdc0d6a49e017e.png

     例如:

    1. int main()
    2. {
    3. int a[] = { 1,2,3,4 };
    4. int* p = a;
    5. int (*pa)[4] = &a;
    6. printf("%p\n", p);
    7. printf("%p\n", p+1);
    8. printf("%p\n", pa);
    9. printf("%p\n", pa+1);
    10. }

     3b3a7c3f1fa74fffbcd288e346175b5d.png

    p    ----------->  p + 1      整形指针加一跳过四个字节 

    pa   -------------->  pa + 1       数组指针加一跳过整个数组

    分析第七个代码:

    printf("%d\n",sizeof(*&a));

    &a是数组的地址,是数组指针类型,*&a是都数组指针解引用,访问一个数组的大小

    则答案为  16

    分析第八个代码:

    printf("%d\n",sizeof(&a+1));

    &a数组的地址,&a+1跳过整个数组,&a+1还是地址,是 4/8 个字节

    则答案为  4(x86环境下)或者8(x64环境下)

    分析第九个代码:

    printf("%d\n",sizeof(&a[0]));

    a[0]是数组的第一个元素,&a[0]是第一个元素的地址,是 4/8 个字节

    则答案为  4(x86环境下)或者8(x64环境下)

    分析第十个代码:

    printf("%d\n",sizeof(&a[0]+1));

    &a[0]是第一个元素的地址,&a[0]+1就是第二个元素的地址,是 4/8 个字节

    则答案为  4(x86环境下)或者8(x64环境下)

    二、字符数组

    1、char arr[] = {'a','b','c','d','e','f'}

    1.sizeof

    1. int main()
    2. {
    3. char arr[] = {'a','b','c','d','e','f'};
    4. printf("%d\n", sizeof(arr));
    5. printf("%d\n", sizeof(arr+0));
    6. printf("%d\n", sizeof(*arr));
    7. printf("%d\n", sizeof(arr[1]));
    8. printf("%d\n", sizeof(&arr));
    9. printf("%d\n", sizeof(&arr+1));
    10. printf("%d\n", sizeof(&arr[0]+1));
    11. return 0;
    12. }

    d6411f428fae4226af2886ba43f422b3.png

     

     

    分析第一个代码:

    printf("%d\n", sizeof(arr));

    arr是数组名,并且是单独放在sizeof内部,计算的是数组总大小,单位是字节 - 6

    则答案为  6

    分析第二个代码:

    printf("%d\n",sizeof(arr+0));

    arr是数组名,并非单独放在sizeof内部,arr表示首元素的地址,arr+0还是首元素的地址,地址大小就是4/8

    则答案为  4(x86环境下)或者8(x64环境下)

    分析第三个代码:

    printf("%d\n",sizeof(*arr));

    arr是首元素的地址,*arr就是首元素,sizeof计算的是首元素的大小,是1字节

    则答案为    1

    分析第四个代码:

    printf("%d\n", sizeof(arr[1]));

    arr[1]是数组的第二个元素,sizeof(arr[1])计算的是第二个元素的大小,1个字节

    则答案为  1

    分析第五个代码:

    printf("%d\n", sizeof(&arr));

    取出的是数组的地址,sizeof(&arr))计算的是数组的地址的大小,地址就是4/8字节

    则答案为   4(x86环境下)或者8(x64环境下)

    分析第六个代码:

    printf("%d\n", sizeof(&arr+1));

    &arr是数组的地址,&arr+1跳过整个数组,指向 'f' 的后边,&arr+1的本质还是地址,是地址就是4/8字节

    则答案为  4(x86环境下)或者8(x64环境下)

    分析第七个代码:

    printf("%d\n", sizeof(&arr[0]+1));

    &arr[0]是‘a’的地址,&arr[0]+1是'b'的地址,  是地址就是4/8字节

    则答案为  4(x86环境下)或者8(x64环境下)

    2.strlen()

    1. #include <string.h>
    2. int main()
    3. {
    4. char arr[] = { 'a','b','c','d','e','f' };
    5. printf("%d\n", strlen(arr));
    6. printf("%d\n", strlen(arr + 0));
    7. //printf("%d\n", strlen(*arr));
    8. //printf("%d\n", strlen(arr[1]));
    9. printf("%d\n", strlen(&arr));
    10. printf("%d\n", strlen(&arr + 1));
    11. printf("%d\n", strlen(&arr[0] + 1));
    12. return 0;
    13. }

    c580eed506ab426fbfad8bcab4dc275b.png

     

    分析第一个代码:

    printf("%d\n", strlen(arr));

    arr是数组名,但是没有放在sizeof内部,也没&,arr就是首元素的地址,strlen得到arr后,从arr数组首元素的地方开始计算字符串的长度,直到直到 ‘\0’,但是arr数组中没有\0,arr内存的后边是否有\0,在什么位置,是不确定的,所以\0之前出现了多少个字符是随机的。

    则答案为   随机值

    分析第二个代码:

    printf("%d\n",strlen(arr+0));

    arr是数组首元素的地址,arr+0还是首元素的地址

    则答案为   随机值

    分析第三个代码:

    printf("%d\n",strlen(*arr));

    arr是数组首元素的地址,*arr 是首元素 ---- ‘a’ - 97

    strlen就把‘a’的ASCII码值 97 当成了地址
    err 会非法访问内存

    分析第四个代码:

    printf("%d\n", strlen(arr[1]));

    arr[1] - 'b' - 98 - err

    分析第五个代码:

    printf("%d\n", strlen(&arr));

    &arr是数组的地址,数组的地址也是指向数组起始位置,和第一个案例一样

    则答案为   随机值

    分析第六个代码:

    printf("%d\n", strlen(&arr+1));

    &arr是数组的地址,&arr+1跳过整个数组,指向 'f' 的后边

    则答案为  随机值

    分析第七个代码:

    printf("%d\n", strlen(&arr[0]+1));

    &arr[0]是‘a’的地址,&arr[0]+1是'b'的地址,

    则答案为  随机值

    2、char arr[] = "abcdef"

    1.sizeof()

    1. int main()
    2. {
    3. char arr[] = "abcdef";
    4. printf("%d\n", sizeof(arr));
    5. printf("%d\n", sizeof(arr + 0));
    6. printf("%d\n", sizeof(*arr));
    7. printf("%d\n", sizeof(arr[1]));
    8. printf("%d\n", sizeof(&arr));
    9. printf("%d\n", sizeof(&arr + 1));
    10. printf("%d\n", sizeof(&arr[0] + 1));
    11. return 0;
    12. }

    27abce5ca00b44328bb2908acae7e58b.png

    (x86环境下)运行结果:

    40a64597daf1405bb2d8e45faf33c8f5.png

    分析第一个代码:

    printf("%d\n", sizeof(arr));

    arr是数组名,并且是单独放在sizeof内部,计算的是数组总大小,单位是字节 - 7

    则答案为  7

    分析第二个代码:

    printf("%d\n",sizeof(arr+0));

    arr是数组名,并非单独放在sizeof内部,arr表示首元素的地址,arr+0还是首元素的地址,地址大小就是4/8

    则答案为  4(x86环境下)或者8(x64环境下)

    分析第三个代码:

    printf("%d\n",sizeof(*arr));

    arr是首元素的地址,*arr就是首元素,sizeof计算的是首元素的大小,是1字节

    则答案为    1

    分析第四个代码:

    printf("%d\n", sizeof(arr[1]));

    arr[1]是数组的第二个元素,sizeof(arr[1])计算的是第二个元素的大小,1个字节

    则答案为  1

    分析第五个代码:

    printf("%d\n", sizeof(&arr));

    取出的是数组的地址,sizeof(&arr))计算的是数组的地址的大小,地址就是4/8字节

    则答案为   4(x86环境下)或者8(x64环境下)

    分析第六个代码:

    printf("%d\n", sizeof(&arr+1));

    &arr是数组的地址,&arr+1跳过整个数组,指向 'f' 的后边,&arr+1的本质还是地址,是地址就是4/8字节

    则答案为  4(x86环境下)或者8(x64环境下)

    分析第七个代码:

    printf("%d\n", sizeof(&arr[0]+1));

    &arr[0]是‘a’的地址,&arr[0]+1是'b'的地址,  是地址就是4/8字节

    则答案为  4(x86环境下)或者8(x64环境下)

    2.strlen()

    1. #include
    2. int main()
    3. {
    4. char arr[] = "abcdef";
    5. printf("%d\n", strlen(arr));
    6. printf("%d\n", strlen(arr + 0));
    7. printf("%d\n", strlen(*arr));
    8. printf("%d\n", strlen(arr[1]));
    9. printf("%d\n", strlen(&arr));
    10. printf("%d\n", strlen(&arr + 1));
    11. printf("%d\n", strlen(&arr[0] + 1));
    12. return 0;
    13. }

    536e850dc63747aa869037743446cdfc.png

    8fd6bd0a586d417a8a7dd2cc6049074b.png

    分析第一个代码:

    printf("%d\n", strlen(arr));

    arr是数组名,但是没有放在sizeof内部,也没&,arr就是首元素的地址,strlen得到arr后,从arr数组首元素的地方开始计算字符串的长度,直到直到 ‘\0’

    则答案为   6

    分析第二个代码:

    printf("%d\n",strlen(arr+0));

    arr是数组首元素的地址,arr+0还是首元素的地址

    则答案为   6

    分析第三个代码:

    printf("%d\n",strlen(*arr));

    arr是数组首元素的地址,*arr 是首元素 ---- ‘a’ - 97

    strlen就把‘a’的ASCII码值 97 当成了地址
    err 会非法访问内存

    分析第四个代码:

    printf("%d\n", strlen(arr[1]));

    arr[1] - 'b' - 98 - err

    分析第五个代码:

    printf("%d\n", strlen(&arr));

    &arr是数组的地址,数组的地址也是指向数组起始位置

    则答案为   6

    分析第六个代码:

    printf("%d\n", strlen(&arr+1));

    &arr是数组的地址,&arr+1跳过整个数组,指向 '\0' 的后边

    则答案为  随机值

    分析第七个代码:

    printf("%d\n", strlen(&arr[0]+1));

    &arr[0]是‘a’的地址,&arr[0]+1是'b'的地址,

    则答案为  5

    3、char *p = "abcdef"

    1.sizeof()

    1. int main()
    2. {
    3. const char* p = "abcdef";
    4. printf("%zu\n", sizeof(p));
    5. printf("%zu\n", sizeof(p + 1));
    6. printf("%zu\n", sizeof(*p));
    7. printf("%zu\n", sizeof(p[0]));
    8. printf("%zu\n", sizeof(&p));
    9. printf("%dzu\n", sizeof(&p + 1));
    10. printf("%zu\n", sizeof(&p[0] + 1));
    11. return 0;
    12. }
    const char* p = "abcdef";

    c3d15396a7fc4c4b9054ec7050ff4122.png

    (x86环境下)运行结果:

     b405ef6443394ea0b8361d603678345d.png

    分析第一个代码:

    printf("%zu\n", sizeof(p));

    p为指针变量,存放地址

    则答案为   4(x86环境下)或者8(x64环境下)

    分析第二个代码:

    printf("%zu\n",sizeof(p+1));

    p存放的是地址,是一个char*的指针,char*的指针加一之后,还是个地址

    加入p里边存放的是(0x0012ff40),则p+1里边存放的是(0x0012ff41)

    则答案为   4(x86环境下)或者8(x64环境下)

    6e7431ac836f40e69348a8ac290cd281.png

    分析第三个代码:

    printf("%zu\n",sizeof(*p));

    p为指针变量,解引用只能访问是1字节

    则答案为    1

    分析第四个代码:

    printf("%zu\n", sizeof(p[0]));

    p[0]  ---------->  *(p+0)

    p存放的是地址,p+0还是原来位置,解引用找到的是第一个元素,第一个元素大小为1个字节

    则答案为  1

    16306f12b494470eb58a7b02e2db6b00.png

    分析第五个代码:

    printf("%zu\n", sizeof(&p));

    &p也是地址,地址就是4/8字节

    则答案为   4(x86环境下)或者8(x64环境下)

    58cdff22b5934b5ea47994c30c0ba8ae.png

    分析第六个代码:

    printf("%zu\n", sizeof(&p+1));

    &arr+1跳过整个p,&arr+1的本质还是地址,是地址就是4/8字节

    则答案为  4(x86环境下)或者8(x64环境下)

    96743402185740789082d30be16252d4.png

    分析第七个代码:

    printf("%zu\n", sizeof(&p[0]+1));

    &arr[0]是‘a’的地址,&arr[0]+1是'b'的地址,  是地址就是4/8字节

    则答案为  4(x86环境下)或者8(x64环境下)

    996ca3150af44e5e9e930ad594e86064.png

    2.strlen()

    1. #include
    2. int main()
    3. {
    4. const char* p = "abcdef";
    5. printf("%d\n", strlen(p));
    6. printf("%d\n", strlen(p + 1));
    7. printf("%d\n", strlen(*p));
    8. printf("%d\n", strlen(p[0]));
    9. printf("%d\n", strlen(&p));
    10. printf("%d\n", strlen(&p + 1));
    11. printf("%d\n", strlen(&p[0] + 1));
    12. return 0;
    13. }
    const char* p = "abcdef";

    c3d15396a7fc4c4b9054ec7050ff4122.png

    运行结果:

    00959bfba22045a38bf82aca15494eea.png

    分析第一个代码:

    printf("%d\n", strlen(p));

    计算字符串的长度,直到直到 ‘\0’

    则答案为   6

    分析第二个代码:

    printf("%d\n",strlen(p+1));

    p存放的是地址,是一个char*的指针,char*的指针加一之后,还是个地址

    加入p里边存放的是(0x0012ff40),则p+1里边存放的是(0x0012ff41)

    则答案为   5

    6e7431ac836f40e69348a8ac290cd281.png

    分析第三个代码:

    printf("%d\n",strlen(*p));

    *p 是首元素 ---- ‘a’ - 97

    strlen就把‘a’的ASCII码值 97 当成了地址
    err 会非法访问内存

    分析第四个代码:

    printf("%d\n", strlen(p[0]));

    arr[0] - 'a' - 97 - err

    分析第五个代码:

    printf("%d\n", strlen(&p));

    &p也是地址(假设的p,p里边存放的是什么不知道)

    则答案为   随机值

    58cdff22b5934b5ea47994c30c0ba8ae.png

    分析第六个代码:

    printf("%d\n", strlen(&arr+1));

    &arr+1跳过整个p(后边是多少不知道)

    则答案为  随机值

    96743402185740789082d30be16252d4.png

    分析第七个代码:

    printf("%d\n", strlen(&arr[0]+1));

    &arr[0]是‘a’的地址,&arr[0]+1是'b'的地址, 

    则答案为  5

    三、二维数组

    1.int a[3][4] = { 0 };

    1. int main()
    2. {
    3. int a[3][4] = { 0 };
    4. printf("%d\n", sizeof(a));
    5. printf("%d\n", sizeof(a[0][0]));
    6. printf("%d\n", sizeof(a[0]));
    7. printf("%d\n", sizeof(a[0] + 1));
    8. printf("%d\n", sizeof(*(a[0] + 1)));
    9. printf("%d\n", sizeof(a + 1));
    10. printf("%d\n", sizeof(*(a + 1)));
    11. printf("%d\n", sizeof(&a[0] + 1));
    12. printf("%d\n", sizeof(*(&a[0] + 1)));
    13. printf("%d\n", sizeof(*a));
    14. printf("%d\n", sizeof(a[3]));
    15. return 0;
    16. }
    int a[3][4] = { 0 };

    d4cae3a03f3f4af8a6f60a8eb8f65178.png

     运行结果:

    78f3afd616e446659c11f60af246a4af.png

     

    分析第一个代码:

    printf("%d\n", sizeof(a));

    a是二维数组的数组名数组名单独放在sizeof内部,计算的是数组的总大小,单位是字节

    则答案为   48

    分析第二个代码:

    printf("%d\n", sizeof(a[0][0]));

    a[0][0]是一个整型元素,大小是4个字节

    则答案为   4

    分析第三个代码:

    printf("%d\n", sizeof(a[0]));

    把二维数组的每一行看做一维数组的时候,a[0]是第一行的数组名,第一行的数组名单独放在sizeof内部,计算的是第一行的总大小,单位是字节

    则答案为   16

    分析第四个代码:

    printf("%d\n", sizeof(a[0] + 1));

    a[0]虽然是第一行的数组名,但是并非单独放在sizeof内部
    a[0]作为第一行的数组名并非表示整个第一行这个数组,a[0]就是第一行首元素的地址

    a[0]--> &a[0][0] - int*
    a[0]+1,跳过一个int,
    是a[0][1]的地址  4/8字节

    则答案为  4(x86环境下)或者8(x64环境下)

    分析第五个代码:

    printf("%d\n", sizeof(*(a[0] + 1)));

    a[0]+1是第一行第二个元素的地址,所以*(a[0]+1)就是a[0][1],大小是4个字节

    则答案为   4

    分析第六个代码:

    printf("%d\n", sizeof(a + 1));

    a是二维数组的数组名,没单独放在sizeof内部,也没有&,所以a就是数组首元素的地址
    二维数组,我们把它想象成一维数组,它的第一个元素就是二维数组的第一行
    a就是第一行的地址,a+1 是第二行的地址,是地址,大小就是 4/8 个字节
    a - &a[0]
    a+1 - &a[1]
    a+2 - &a[2]

    则答案为   4(x86环境下)或者8(x64环境下)

    分析第七个代码:

    printf("%d\n", sizeof(*(a + 1)));

    a+1是第二行的地址,*(a+1) 找到的就是第二行,sizeof(*(a + 1))计算的就是第二行的大小
    *(a+1) --> a[1]
    sizeof(*(a + 1)) --> sizeof(a[1])

    则答案为  16

    分析第八个代码:

    printf("%d\n", sizeof(&a[0] + 1));

    &a[0]是第一行的地址,&a[0]+1就是第二行的地址,sizeof(&a[0] + 1)计算的第二行地址大小,单位是字节 - 4/8,

    则答案为  4(x86环境下)或者8(x64环境下)

    分析第九个代码:

    printf("%d\n", sizeof(*(&a[0] + 1)));

    &a[0] + 1是第二行的地址,*(&a[0] + 1)拿到的就是第二行,大小就是16个字节
    //    //*(&a[0]+1) --> a[1]

    则答案为   16

    分析第十个代码:

    printf("%d\n", sizeof(*a));

    a表示首元素的地址,就是第一行的地址 - &a[0]
    *a - 拿到的就是第一行 -------- 大小就是16个字节
    *a -> *(a+0) -> a[0]

    则答案为  16

    分析第十一个代码:

    printf("%d\n", sizeof(a[3]));

    首先这个代码没问题

    a[3]是二维数组的第4行,虽然没有第四行,但是类型能够确定,大小就是确定的。大小就是

    一行的大小,单位是字节 - 16

    能够分析出 a[3]的类型是:int [4]
    任何一个表达式有2个属性
    例如:3+5
    值属性:8
    类型属性:int

    则答案为  16

     

     

     

     

     

     

  • 相关阅读:
    PC_访存过程@内存地址翻译过程@具有快表TLB和cache的多级存储系统
    threejs要点你值得学习
    【SpringBoot实战系列】从AOP+自定义注解到redission分布式锁-接口防重提交场景设计实战
    力扣(LeetCode)799. 香槟塔(C++)
    【7】Spring Boot 3 集成组件:缓存组件 spring cache + spring data redis
    【案例实践】HEC-RAS 1D/2D水动力与水环境模拟、HEC-RAS与HEC-FDA耦合、桥梁分析、泄洪道设定
    【分布式系统】分布式选举之Bully算法
    软考 网络工程师如何复习?
    学校项目培训之Carla仿真平台之Carla学习内容
    Bancet开源驱动SDK开发包Java版,开箱即用(楼宇自控,智慧楼宇,智能建筑)
  • 原文地址:https://blog.csdn.net/m0_72161237/article/details/126534518