指针和数组有关sizeof/strlen的解读,全是干货!

对于整形数组:

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

printf("%d\n",sizeof(a)); 此处a代表整个数组的大小,类型是int(*)【4】,大小是16

printf("%d\n",sizeof(a+0));此处a+0代表数组首元素的地址,类型是int*,大小4或者8

printf("%d\n",sizeof(*a));此处*a表示数组首元素,类型是int,大小是4

printf("%d\n",sizeof(a+1));此处a+1表示数组第二个元素的地址,类型int*,大小是4或者8

printf("%d\n",sizeof(a[1]));数组第二个元素,类型int,大小4

printf("%d\n",sizeof(&a));数组的地址,类型int**,大小4或8

printf("%d\n",sizeof(*&a));*和&抵消,可视为sizeof(a),大小16

printf("%d\n",sizeof(&a+1));指向数组后第一个字节的位置,类型和&a相同,大小4或8

printf("%d\n",sizeof(&a[0]));表示数组首元素的地址,类型int*,大小4或8

printf("%d\n",sizeof(&a[0]+1));表示数组第二个元素的地址,类型int*,大小4或8

对于字符数组:

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

printf("%d\n", sizeof(arr));整个数组的大小,类型是char【6】,大小6

printf("%d\n", sizeof(arr+0));数组首元素的地址,类型char*,大小4或8

printf("%d\n", sizeof(*arr));数组首元素,类型char,大小1

printf("%d\n", sizeof(arr[1]))数组第二个元素,类型char,大小1

printf("%d\n", sizeof(&arr));数组的地址,类型char(*)【6】,大小4或8

printf("%d\n", sizeof(&arr+1));跳过整个数组,指向数组后第一个字节,类型char(*)【6】,大小4或8

printf("%d\n", sizeof(&arr[0]+1));数组第二个元素的地址,类型char*,大小4或8

printf("%d\n", strlen(arr)); 内部是数组首元素的地址,结果未知,因为arr中没有\0作为结束标志

printf("%d\n", strlen(arr+0));内部是数组首元素的地址,结果未知,因为arr中没有\0作为结束标志

printf("%d\n", strlen(*arr));内部是数组首元素,相当于把‘a’的ascii值作为地址,非法访问。

printf("%d\n", strlen(arr[1]));内部是数组首元素,相当于把‘a’的ascii值作为地址,非法访问。

printf("%d\n", strlen(&arr));内部是数组的地址,结果未知。

printf("%d\n", strlen(&arr+1));内部是跨国数组的第一个字节的地址,结果未知。

printf("%d\n", strlen(&arr[0]+1));内部是第二个元素的地址,结果未知,因为arr中没有\0。

char arr[] = "abcdef";

printf("%d\n", sizeof(arr));表示数组大小,类型char【7】,大小7.

printf("%d\n", sizeof(arr+0));表示数组首元素的地址,类型char*,大小4或8.

printf("%d\n", sizeof(*arr));表示数组第一个元素,类型char,大小1。

printf("%d\n", sizeof(arr[1]));表示数组第二个元素,类型char,大小1.

printf("%d\n", sizeof(&arr));表示数组的地址,类型char(*)【7】,大小4或8.

printf("%d\n", sizeof(&arr+1));表示跨过整个数组后的地址,类型char(*)【7】,大小4或8.

printf("%d\n", sizeof(&arr[0]+1));表示数组第二个元素的地址,类型char*,大小4或8.

printf("%d\n", strlen(arr));表示数组首元素的地址,大小6.

printf("%d\n", strlen(arr+0));表示数组首元素地址,大小6

printf("%d\n", strlen(*arr));表示数组第一个元素,将其ascii看做地址大小,非法访问。

printf("%d\n", strlen(arr[1]));表示数组第二个元素,同上

printf("%d\n", strlen(&arr));表示整个数组地址,大小6

printf("%d\n", strlen(&arr+1));表示跨过整个数组后的地址,大小未知

printf("%d\n", strlen(&arr[0]+1));表示数组第二个元素地址,大小5.

char *p = "abcdef";

printf("%d\n", sizeof(p));表示数组首元素的地址,类型char*,大小4或8

printf("%d\n", sizeof(p+1));表示数组第二个元素的地址,类型char*,大小4或8

printf("%d\n", sizeof(*p));表示数组首元素,类型char,大小1

printf("%d\n", sizeof(p[0]));表示数组首元素,类型char,大小1

printf("%d\n", sizeof(&p));表示指针的地址,类型char**,大小4或8

printf("%d\n", sizeof(&p+1));表示指针的地址的下一位,类型char**,大小4或8

printf("%d\n", sizeof(&p[0]+1));表示数组第二个元素的地址,类型char*,大小4或8

printf("%d\n", strlen(p));表示数组首元素的地址,大小6

printf("%d\n", strlen(p+1));表示数组第二个元素的地址,大小5

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));表示数组第二个元素的地址,大小5

对于二维数组:

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

printf("%d\n",sizeof(a));表示数组的地址,类型int【3】【4】,大小48

printf("%d\n",sizeof(a[0][0]));表示数组首元素,类型int,大小4

printf("%d\n",sizeof(a[0]));表示第一个一维数组的地址,类型int【4】,大小16

printf("%d\n",sizeof(a[0]+1));表示第二个元素a【0】【1】的地址,类型int*,大小4或8

printf("%d\n",sizeof(*(a[0]+1)));表示数组第二个元素a【0】【1】,类型int,,大小4

printf("%d\n",sizeof(a+1));表示数组第二个一维数组数组的地址,类型int(*)【4】,大小4或8

printf("%d\n",sizeof(*(a+1)));表示数组第二个一维数组,类型int【4】,大小16

printf("%d\n",sizeof(&a[0]+1));表示数组第二个一维数组的地址,类型int(*)【4】,大小4或8

printf("%d\n",sizeof(*(&a[0]+1)));表示数组第二个一维数组,类型int【4】,大小16

printf("%d\n",sizeof(*a));表示a【0】,类型类型int【4】,大小16

printf("%d\n",sizeof(a[3]))类型类型int【4】,大小16

int main() {

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

int *ptr = (int *)(&a + 1);

printf( "%d,%d", *(a + 1), *(ptr - 1));

return 0; }

本题ptr指向数组后第一个字节的位置,ptr减一则往前移动一个指针大小的字节,指向a【4】的地址,解引用为a【4】的值,为5

a+1表示数组第二个元素的地址,即&a【1】,解引用是a【1】,大小2.

int main() {

char*p=(char*)ox001.

printf("%p\n", p + 0x1);

printf("%p\n", (unsigned long)p + 0x1);

printf("%p\n", (unsigned int*)p + 0x1);

return 0;

}

p的类型是char*,加ox1相当跳过一个char类型,即加ox1,值为ox(1+1)

(unsign long)p的类型是unsigned long,加ox1就是加数字ox1,值为ox(1+1)

(unsigned int*)类型是unsigned int*,加ox1就是加一个int类型,值为ox(4+1)

一般来说指针加1就是加1个指针所指类型的数据的大,但应当注意对于指向数组的指针,一次是跳过数组的一个元素。

int main() {

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

int *ptr1 = (int *)(&a + 1);

int *ptr2 = (int *)((int)a + 1);

printf( "%x,%x", ptr1[-1], *ptr2);

return 0;

}

ptr1指向数组后第一个字节的位置,ptr1【-1】可视为*(ptr1-1),其中ptr1-1就是减去一个int大小的地址,指向a【3】的地址,解引用是a【3】,大小4

(int)a+1就是在数组首元素的地址的基础上加1个字节,根据小端存储,ptr2的数据是ox02000000。指针和数组有关sizeof/strlen的解读,全是干货!_第1张图片

int main() {

int a[3][2] = { (0, 1), (2, 3), (4, 5) };

int *p;

p = a[0];

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

return 0;

}

p【0】可视为a【0】【0】,故为1

此处应当注意数组的元素,均是由逗号表达式组成的表达式,而逗号表达式只要最后一个元素,因此初始化二维数组可等价于int a【3】【2】={1,3,5}

int main() {

int a[5][5];

int(*p)[4];

p = a;

printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);

return 0;

}

此处p【4】【2】指向数组a的第4*4+2=18的位置,即数组第19个元素,a【4】【2】指向数组a的第4*5+2=22的位置,即数组第23个元素。因此相减的结果是19-23=-4,%p的结果是-4的补码,即oxfffffffc,%d的结果是-4.

int main() {

int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

int *ptr1 = (int *)(&aa + 1);

int *ptr2 = (int *)(*(aa + 1));

printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));

return 0;

}

&aa+1跳过整个数组,减一后指向数组最后一个元素,即a【9】,大小是10

aa+1跳过一个一维数组,指向aa【1】,解引用就是aa【1】【0】的地址,减一就是aa【0】【4】的地址,即5.

应当注意二维数组可视为多个一维数组连续存放,,即在地址上是一直相连的。

int main() {

char *a[] = {"work","at","alibaba"};

char**pa = a;

pa++;

printf("%s\n", *pa);

return 0;

}

pa的类型是char**,,其内容是数组首元素的地址,pa++指向数组第二个元素,即a【1】,结果为at。

应注意

你可能感兴趣的:(算法,数据结构,c++)