目录

讨论数组名

sizeof & strlen

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

sizeof(a)

sizeof(a + 0)

sizeof(*a)

sizeof(a + 1)

sizeof(a[1])

sizeof(&a)

sizeof(*&a)

sizeof(&a + 1)

sizeof(&a[0])

sizeof(&a[0] + 1)

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

sizeof(arr)

sizeof(arr + 0)

sizeof(*arr)

sizeof(arr[1])

sizeof(&arr)

sizeof(&arr + 1)

sizeof(&arr[0] + 1)

♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥

strlen(arr)

strlen(arr + 0)

 strlen(*arr)

strlen(arr[1])

strlen(&arr)

strlen(&arr + 1)

strlen(&arr[0] + 1)

char arr[] = "abcdef"

sizeof(arr)

sizeof(arr + 0)

sizeof(*arr)

sizeof(arr[1])

sizeof(&arr)

sizeof(&arr + 1)

sizeof(&arr[0] + 1)

♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥

strlen(arr)

strlen(arr + 0)

strlen(*arr)

strlen(arr[1])

strlen(&arr)

strlen(&arr + 1)

strlen(&arr[0] + 1)

char *p = "abcdef"

sizeof(p)

sizeof(p + 1)

sizeof(*p)

sizeof(p[0])

sizeof(&p)

sizeof(&p + 1)

sizeof(&p[0] + 1)

♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥

strlen(p)

strlen(p + 1)

strlen(*p)

strlen(p[0])

strlen(&p)

strlen(&p + 1)

 strlen(&p[0] + 1)

int a[3][4] = {0}

sizeof(a)

sizeof(a[0][0])

sizeof(a[0])

sizeof(a[0] + 1)

sizeof(*(a[0] + 1))

sizeof(a + 1)

sizeof(*(a + 1))

sizeof(&a[0] + 1)

sizeof(*(&a[0] + 1))

sizeof(*a)

sizeof(a[3])


讨论数组名

数组名通常表示的都是数组首元素的地址
但是有2个例外:
   1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小
   2. &数组名,这里的数组名表示的依然是整个数组,所以&数组名取出的是整个数组的地址

sizeof & strlen

  • sizeof只关注占用内存空间的大小,不在乎内存中放的是什么,所以\0也算一个字符(只针对字符串)
  • strlen是求字符串长度的,关注的是字符串中\0,计算的是\0之前出现的字符的个数(strlen是操作符)

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

sizeof(a)

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

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

sizeof(a + 0)

a不是单独放在sizeof内部,也没有取地址,所以a就是数组首元素的地址,指针地址的大小是4/8个字节,当前是64位,即8 

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

sizeof(*a)

a代表数组首元素地址,解引用得到第一个int值,int是 4 个字节

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

sizeof(a + 1)

a代表数组首元素地址,a+1,是第二个元素的地址,sizeof(a+1)就是地址的大小,4/8,当前64位,即8

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

sizeof(a[1])

 a[1] ——> *(a+1),也就是第二个int值的大小,同样是 4 个字节

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

sizeof(&a)

&a 等同于 a+0,同样是指针地址的大小,即4/8个字节,当前是64位,即8,(如果去掉&,大小就是16) 

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

sizeof(*&a)

*和& 可以看做同时抵消,只剩a,那么就是整个数组的大小(&a-->int(*)[4],&a拿到的是数组名的地址,类型是int(*)[4],是一种数组指针,数组指针解引用找到的是数组,*&a-->a)

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

sizeof(&a + 1)

&a取出是数组的地址,&a+1 跳过了整个数组的字节(16)所指向的地址,但同样是指针的大小,即4/8个字节,当前是64位,即8

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

sizeof(&a[0])

 第一个元素的地址大小.同样是指针地址的大小,即4/8个字节,当前是64位,即8

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

sizeof(&a[0] + 1)

第二个元素的地址大小,同样是指针地址的大小,即4/8个字节,当前是64位,即8

sizeof(&a[0] + 1)

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

sizeof(arr)

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

sizeof(arr + 0)

printf("%d\n", sizeof(arr + 0));     // 8 首元素地址大小,4/8

sizeof(*arr)

printf("%d\n", sizeof(*arr));        // 1 首元素地址解引用,a的字节大小

sizeof(arr[1])

printf("%d\n", sizeof(arr[1]));      // 1 第2个元素大小

sizeof(&arr)

printf("%d\n", sizeof(&arr));        // 8 取数组的地址,地址就是地址,4/8

sizeof(&arr + 1)

printf("%d\n", sizeof(&arr + 1));    // 8 跳过整个数组的地址,4/8

sizeof(&arr[0] + 1)

printf("%d\n", sizeof(&arr[0] + 1)); // 8 第2个元素的地址,4/8

♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥

strlen(arr)

printf("%d\n", strlen(arr));     // 随机值,找到 \0 才停止

strlen(arr + 0)

printf("%d\n", strlen(arr + 0)); // 随机值,arr首元素地址+0还是首元素地址,等同于上式

 strlen(*arr)

 报错, strlen接收字符指针作为参数,而 strlen(*arr) -- strlen('a') -- strlen(97),而97相当于是个野指针,并不属于a

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

strlen(arr[1])

 报错,相当于 strlen('b') -- strlen(61) 同上也是野指针

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

strlen(&arr)

printf("%d\n", strlen(&arr)); // 随机值,取数组地址,本质也是首元素地址

strlen(&arr + 1)

printf("%d\n", strlen(&arr + 1)); // 随机值 - 6,&arr跳过整个数组取地址

strlen(&arr[0] + 1)

rintf("%d\n", strlen(&arr[0] + 1)); // 随机值 - 1, &arr[0] 第一个元素地址

char arr[] = "abcdef"

sizeof(arr)

printf("%d\n", sizeof(arr)); // 7 这里默认补 \0

sizeof(arr + 0)

printf("%d\n", sizeof(arr + 0)); // 8  a的地址+0,还是a的地址,4/8 

sizeof(*arr)

printf("%d\n", sizeof(*arr)); // 1 *arr就是元素a

sizeof(arr[1])

printf("%d\n", sizeof(arr[1])); // 1 元素b

sizeof(&arr)

printf("%d\n", sizeof(&arr)); // 8,数组地址,4/8

sizeof(&arr + 1)

printf("%d\n", sizeof(&arr + 1)); // 8 &arr + 1 移动一个数组的长度,即指向数组 arr 之后的一个内存位置,指向 arr 数组结束的位置之后的地址, 指针大小,即4/8

sizeof(&arr[0] + 1)

printf("%d\n", sizeof(&arr[0] + 1)); // 8 元素a的地址

♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥

strlen(arr)

    /* 6 截取\0之前的字符个数 */
    printf("%d\n", strlen(arr));

strlen(arr + 0)

    /* 6 同上 */
    printf("%d\n", strlen(arr + 0));

strlen(*arr)

    /* 报错,同上上上上上 */
    printf("%d\n", strlen(*arr));

strlen(arr[1])

    /* 报错,同上上上上上 */
    printf("%d\n", strlen(arr[1]));

strlen(&arr)

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

strlen(&arr + 1)

    /* 随机值 跳过整个数组,\0也会跳过,它不知道所指向的下个字符数组的地址个数有几个元素 */
    printf("%d\n", strlen(&arr + 1));

strlen(&arr[0] + 1)

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

char *p = "abcdef"

sizeof(p)

    /*  8 这里是指针变量的大小 */
    printf("%d\n", sizeof(p));

sizeof(p + 1)

    /* 8 b的地址 */
    printf("%d\n", sizeof(p + 1));

sizeof(*p)

    /* 1 */
    printf("%d\n", sizeof(*p));

sizeof(p[0])

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

sizeof(&p)

    /* 8 指针变量大小 */
    printf("%d\n", sizeof(&p));

sizeof(&p + 1)

    /* 8 */
    printf("%d\n", sizeof(&p + 1));

sizeof(&p[0] + 1)

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

♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥

strlen(p)

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

strlen(p + 1)

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

strlen(*p)

    /* 报错,*p == 96 */
    printf("%d\n", strlen(*p));

strlen(p[0])

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

strlen(&p)

    /* 随机值,p本身就是地址,再取地址,相当于取指针变量p的地址,两个地址之间毫无关系 */
    printf("%d\n", strlen(&p));

strlen(&p + 1)

    /* 随机值 */
    printf("%d\n", strlen(&p + 1));

 strlen(&p[0] + 1)

    /* 5 p[0] == 元素a,&a+1即5 */
    printf("%d\n", strlen(&p[0] + 1));

int a[3][4] = {0}

sizeof(a)

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

sizeof(a[0][0])

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

sizeof(a[0])

a[0]相当于第一个数组,只有一个数组名,计算当前数组的大小

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

sizeof(a[0] + 1)

 arr[0]是表示首元素的地址,本质是数组名(又等于第一行数组首元素的地址),等同于第一个数组的arr+1。也就是第一行第二个元素的地址

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

sizeof(*(a[0] + 1))

第一行第二个元素的大小

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

sizeof(a + 1)

a虽然是二维数组的地址,但是并没有单独放在sizeof内部,也没取地址,a表示首元素的地址,二维数组的首元素是它的第一行,a就是第一行的地址,+1跳过一行的数组,表示第二行的地址

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

sizeof(*(a + 1))

第二行数组地址的解引用,拿到了整个第二行,sizeof内只有数组名,求整个第二行数组的大小

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

sizeof(&a[0] + 1)

&a[0]对第一行的数组名取地址,拿出的是第一行的地址,&a[0]+1 得到的是第二行的地址

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

sizeof(*(&a[0] + 1))

第二行的地址解引用,得到第二行的数组名arr,sizeof内部只有arr,即计算整个第二行数组的大小 

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

sizeof(*a)

解引用整个二维数组的地址,即解引用二维数组首元素第一行数组的地址,再解引用第一行的地址得到arr,只有arr,计算整个第一行数组大小 

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

sizeof(a[3])

超界不会真正访问第四行的,其会根据int类型,就可以推算到,等同于a[0]

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

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐