温故而知新
指针和数组笔试题解析
一维数组
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));//16
//sizeof(a)是数组名单独放在sizeof内部,计算的数组总大小,单位是字节
printf("%d\n", sizeof(a + 0));//4/8
//a+0其实是数组首元素的地址
printf("%d\n", sizeof(*a));//4
//a是数组首元素的地址 - &a[0]
//*a - *&a[0]- a[0]
printf("%d\n", sizeof(a + 1));//4/8
//a是数组首元素的地址 int*
//a+1跳过一个整型,是第二个元素的地址
printf("%d\n", sizeof(a[1]));//4
printf("%d\n", sizeof(&a));//4/8
//&a-取出的是数组的地址,但是数组的地址也是地址,是地址大小就是4/8个字节
//int (*pa)[4] = &a;//int(*)[4]
printf("%d\n", sizeof(*&a));//16
//sizeof(a)
//int(*)[4]
printf("%d\n", sizeof(&a + 1));
//&a int(*)[4]
//&a+1 跳过一个数组
printf("%d\n", sizeof(&a[0]));//4/8
printf("%d\n", sizeof(&a[0] + 1));//4/8
字符数组
1.sizeof计算的是占用内存空间的大小,单位是字节,不关注内存中到底存放的是什么
2.sizeof不是函数,是操作符
3.strlen是函数
4.strlen是针对字符串的,求的是字符串的长度,本质上统计的是\0之前出现的字符个数
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));//6
printf("%d\n", sizeof(arr+0));//arr+0是数组首元素的地址 4/8
printf("%d\n", sizeof(*arr));//*arr是首元素,计算的是首元素的大小 1
printf("%d\n", sizeof(arr[1]));//1
printf("%d\n", sizeof(&arr));//&arr是数组的地址 4/8
printf("%d\n", sizeof(&arr+1));//&arr+1 跳过一个数组后的地址 4/8
printf("%d\n", sizeof(&arr[0]+1));//4/8 第二个元素的地址
printf("%d\n", strlen(arr));//随机值 因为不知道\0位置
printf("%d\n", strlen(arr+0));//随机值
printf("%d\n", strlen(*arr));//strlen只能接收的是地址 'a' = 97 把97当成地址了 非法访问
printf("%d\n", strlen(arr[1]));//'b' = 98 当成地址 形参非法访问
printf("%d\n", strlen(&arr));//随机值
printf("%d\n", strlen(&arr+1));//随机值 - 6
printf("%d\n", strlen(&arr[0]+1));//随机值 - 1
char arr[] = "abcdef";//[a b c d e f \0]
printf("%d\n", sizeof(arr));//7
printf("%d\n", sizeof(arr+0));//4/8
printf("%d\n", sizeof(*arr));//是 数组首元素
// arr[0] *(arr+0)
//int sz = sizeof(arr)/sizeof(*arr);
//int sz = sizeof(arr)/sizeof(arr[0]);
printf("%d\n", sizeof(arr[1]));//1
printf("%d\n", sizeof(&arr));//数组的地址 4/8
printf("%d\n", sizeof(&arr+1));//跳过一个数组 4/8
printf("%d\n", sizeof(&arr[0]+1));//4/8
printf("%d\n", strlen(arr));//6
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]
printf("%d\n", strlen(&arr+1));//随机值
printf("%d\n", strlen(&arr[0]+1));//5
char *p = "abcdef";
printf("%d\n", sizeof(p));//4/8
printf("%d\n", sizeof(p+1));//'b' 的地址 4/8
printf("%d\n", sizeof(*p));//1
printf("%d\n", sizeof(p[0]));//*(p + 0 ) == 'a' 1
printf("%d\n", sizeof(&p));//4/8 二级指针
printf("%d\n", sizeof(&p+1));// 4/8
//p == char* &p == char**
printf("%d\n", sizeof(&p[0]+1));//4/8 'b'的地址
printf("%d\n", strlen(p));//6
printf("%d\n", strlen(p+1));//5 p+1是'b'的地址
printf("%d\n", strlen(*p));//err
printf("%d\n", strlen(p[0]));//err
printf("%d\n", strlen(&p));//随机值
printf("%d\n", strlen(&p+1));//随机值 与前者无关系 !!!
printf("%d\n", strlen(&p[0]+1));//5
注意这三种写法的区别
char arr[] = {'a','b','c','d','e','f'};
char arr[] = "abcdef";//[a b c d e f \0]
char *p = "abcdef";
二维数组
int a[3][4] = {0};//数组在内存中是连续存放的
printf("%d\n",sizeof(a));// 48 a这个二维数组的数组名单独放在sizeof内部 ,计算整个数组的大小
printf("%d\n",sizeof(a[0][0]));//第一行第一个元素 4个字节
printf("%d\n",sizeof(a[0]));//16
//a[0]是第一行的数组名 这是数组名单独放在 sizeof内部
//计算的是数组的大小 16 单位是字节
printf("%d\n",sizeof(a[0]+1));//a[0]不是单独放在sizeof内部 ,a[0]表示首元素的地址 即第一行第一个元素的地址 &a[0][0]
//a[0]+1 是第一行第二个元素的地址 &a[0][1]
printf("%d\n",sizeof(*(a[0]+1)));//a[0][1] 大小4个字节
printf("%d\n",sizeof(a+1));
//a作为二维数组的数组名并非单独放在sizeof内部,所以表示首元素的地址
//二维数组的首元素是第一行 ,这里的a就是第一行的地址 int(*)[4]
//a+1 是跳过了第一行,指向了第二行 等价于&a[1]
printf("%d\n",sizeof(*(a+1)));//16
//*(a+1) == a[1]
printf("%d\n",sizeof(&a[0]+1));
//&a[0]是第一行的地址
//&a[0]+1 是第二行的地址
printf("%d\n",sizeof(*(&a[0]+1)));//16 a[1]
printf("%d\n",sizeof(*a));//16 *a就是第一行 *(a+0) a[0]
printf("%d\n",sizeof(a[3]));//16 不越界 因为没有真的访问
printf("%d\n",sizeof(*arr+1));//4/8
//*arr == arr[0] arr[0]+1 ==> &arr[0][0] + 1 ==> &arr[0][1]
可通过下图来理解:
最后一行代码为什么不越界?可以看下面这个小例子
#include <stdio.h>
int main()
{
int a = 5;
short s = 11;
printf("%d\n", sizeof(s = a + 2));//2 sizeof内部的表达式不会真的计算,通过类型可推断为2
printf("%d\n", s);//11
return 0;
}
指针笔试题
笔试1
#include <stdio.h>
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int* ptr = (int*)(&a + 1);
printf("%d,%d", *(a + 1), *(ptr - 1));// 2 5
return 0;
}
//程序的结果是什么?
笔试2
#include <stdio.h>
//由于还没学习结构体,这里告知结构体的大小是20个字节
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
printf("%p\n", p + 0x1);//加一 跳过20个字节 0x100014
printf("%p\n", (unsigned long)p + 0x1);//变成整型 0x100001 整型加一
printf("%p\n", (unsigned int*)p + 0x1);//0x100004 指针加一
return 0;
}