1.sizeof与strlen计算
2.指针面试题
(1) 一维数组相关计算
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a)); //16 数组中有4个整型Int类型的元素
printf("%d\n", sizeof(a + 0)); //4 数组名参与运算时会隐式转换为指向首元素(地址)的指针;再加减操作时指针移动的字节数;移动完仍是指针Int* 类型
printf("%d\n", sizeof(*a)); //4 数组名隐式转化为指针 int* ,在进行解引用成 Int 类型
printf("%d\n", sizeof(a + 1)); //4 数组名参与运算转化为指针,在加减仍为int* 类型
printf("%d\n", sizeof(a[1])); //4 表示数组第二个元素所占内存大小,类型位int
printf("%d\n", sizeof(&a)); //4 int[4]数组->int(*)[4]数组指针
printf("%d\n", sizeof(*&a)); //16 &a:int(*)[4]->再解引用得到int[4]
printf("%d\n", sizeof(&*a)); //4 *a:inta[0]->加& 得到一个指针指向第一个元素 * a[0]
printf("%d\n", sizeof(&a + 1)); //4 &a:int(*)[4]->再加减操作仍为指针类型
printf("%d\n", sizeof(&a[0] + 1)); //4 &a[0]:int* +1 -> 仍为int*类型
char a[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(a)); //6 数组a中 6 个元素都为char 类型
printf("%d\n", sizeof(a + 0)); //4 类型为char *
printf("%d\n", sizeof(*a)); //1 a转化char*类型->*解引用为char类型
printf("%d\n", sizeof(a[1])); //1 求数组第二个元素内存大小,为char型
printf("%d\n", sizeof(&a)); //4 &a:char(*)[6]指针类型
printf("%d\n", sizeof(&a+1)); //4 &a:char(*)[6] 再+1->指针类型
printf("%d\n", sizeof(&a[0]+1)); //4 &a[0]:char * 再+1->仍为指针
printf("%d\n", sizeof(*&a)); //6 &a:char(*)[6] 再*解引用->为char[6]
printf("%d\n", sizeof(&*a)); //4 *a:char -> &*a:char *指针类型
printf("%d\n", strlen(a)); //不确定值 因为strlen函数结束标志是遇到\0结束计算,不确定遍历完数组元素之后往后哪一个位置为0/\0;
printf("%d\n", strlen(a + 0)); //不确定值 同上传入指针进行遍历计算遇到\0结束
printf("%d\n", strlen(*a)); //未定义行为 *a为char类型 strlen参数为 const char * 类型
printf("%d\n", strlen(a[1])); //未定义行为 同上
printf("%d\n", strlen(&a)); //未定义行为 &a:char(*)[6]类型 与strlen实参const char*类型不匹配
printf("%d\n", strlen(&a + 1)); //未定义行为 &a+1 相当于数组指针跳过数组指向后一个字节 仍然是参数不匹配
printf("%d\n", strlen(&a[0] + 1)); //未定义行为 &a[0]+1 -> 相当于传入一个指向 'b'的char *
(3) 字符串
char a[] = "abcdef";
printf("%d\n", sizeof(a)); //7 字符串常量,默认结尾有\0,故char型数组a[7]
printf("%d\n", sizeof(a + 0)); //4 char *
printf("%d\n", sizeof(*a)); //1 a隐式转换为char * -> 再解引用为char
printf("%d\n", sizeof(a[1])); //1 char
printf("%d\n", sizeof(a[1]+1)); //4 a[1]:char -> 再+1 整型提升得到 int
printf("%d\n", sizeof(&a)); //4 &a:char(*)[7]
printf("%d\n", sizeof(&a + 1)); //4 char(*)[7]+1 仍为指针类型
printf("%d\n", sizeof(&a[0] + 1)); //4 char *
printf("%d\n", sizeof(*&a)); //7 &a:char(*)[7] -> 再解引用 char[7]
printf("%d\n", sizeof(&*a)); //4 *a:char * -> 再& 得到char *
printf("%d\n", sizeof(*&a + 1)); //4 *&a得到数组 +1 -> char *
printf("%d\n", sizeof(*&(a + 1))); //编译不过 a + 1 这个表达式不是左值, 没有在内存中创建空间, 不能 &
printf("%d\n", strlen(a)); //6 计算字符串“abcdef”长度
printf("%d\n", strlen(a + 0)); //6 从 'a' 这个位置开始找 \0
//printf("%d\n", strlen(*a)); //未定义行为 *a 得到了 char, strlen 形参是 const char*
//printf("%d\n", strlen(a[1])); //未定义行为
printf("%d\n", strlen(&a)); //6 理论上来讲是不应该编译通过的. &a 得到了 char(*)[7] 这个类型, strlen 要求的是 const char* 类型, 此处在 C 中会触发隐式类型转换. 地址值不变, 相当于从 'a' 往后找 '\0'
//printf("%d\n", strlen(&a + 1)); //未定义行为 &a + 1 导致指针跳过 整个数组, 也跳过了 \0
printf("%d\n", strlen(&a[0] + 1)); //5 a[0] 'a' , 再取地址, 得到了 char*, 再 + 1, 指向了 'b'
(4) 字符串指针
char* p = "abcdef";
printf("%d\n", sizeof(p)); //4 p为char *类型
printf("%d\n", sizeof(p + 1)); //4 仍为char *
printf("%d\n", sizeof(*p)); //1 char
printf("%d\n", sizeof(p[0])); //1 p[0] -> char
printf("%d\n", sizeof(&p)); //4 &p -> char **
printf("%d\n", sizeof(&p + 1));//4 char ** +1成为 指针类型
printf("%d\n", sizeof(&p[0] + 1));//4 char * +1 -> char *
printf("%d\n", strlen(p)); //6 指针p指向字符串常量"abcdef",计算字符长度
printf("%d\n", strlen(p + 1)); //5 从第二个字符向后计算长度,截止到\0
//printf("%d\n", strlen(*p)); //未定义行为 *p => char, strlen 要求的是 const char* 类型
//printf("%d\n", strlen(&p)); //未定义行为 &p => char**
//printf("%d\n", strlen(&p + 1));//未定义行为 同上
printf("%d\n", strlen(&p[0] + 1)); //5
int a[3][4] = { 0 };
printf("%d\n", sizeof(a)); //48 总的大小 3 * 4 * 4
printf("%d\n", sizeof(a[0][0])); //4 a[0][0] => int
printf("%d\n", sizeof(a[0])); //16 a[0] => int[4]
printf("%d\n", sizeof(a[0] + 1)); //4 a[0] => int[4] 再 + 1, 就成了 int*
printf("%d\n", sizeof( *(a[0] + 1) ) ); //4 a[0] => int[4], 再 + 1 得到 int*, 再解引用得到 int
printf("%d\n", sizeof(a + 1)); //4 a是 int[3][4] , + 1 就会隐式转成指针, int(*)[4]
printf("%d\n", sizeof(*(a + 1))); //16 *(a + 1) => a[1] => int[4]
printf("%d\n", sizeof(&a[0] + 1)); //4 a[0] => int[4], 再来 &, 得到 int(*)[4], 再来一个 + 1 还是 int(*)[4]
printf("%d\n", sizeof( *(&a[0] + 1) )); //16 a[0] => int[4], 再 &, 得到 int(*)[4], 再+1, 类型还是 int(*)[4], 再来 *, int[4]
printf("%d\n", sizeof(*a)); //16 *a => a[0]-> int[4]
1>下面这段程序的输出结果为?
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);
printf( "%d,%d", *(a + 1), *(ptr - 1));
return 0;
}
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
int main(){
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
分析:
3>下面这段程序的输出结果为?
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;
}
int main(int argc, char* argv[])
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int* p;
p = a[0];
printf("%d", p[0]);
}
5>下面这段程序的输出结果为?
int main(){
int a[5][5];
int(*p)[4];
p = a;
printf("a_ptr=%#p,p-ptr=%#p\n", &a[4][3], &p[4][3]);
printf("%p,%d\n", &p[4][3] - &a[4][3], &p[4][3] - &a[4][3]);
}
6>下面这段程序的输出结果为?
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));
}
int mian(){
char* a[] = { "work","at","alibaba" };
char** pa = a;
pa++;
printf("%s\n", *pa);
}
int main(){
char* c[] = { "ENTER","NEW","POINT","FIRST" };
char** cp[] = { c + 3,c + 2,c + 1,c };
char*** cpp = cp;
printf("%s\n", **++cpp);
printf("%s\n", *--* ++cpp + 3);
printf("%s\n", *cpp[-2] + 3);
printf("%s\n", cpp[-1][-1] + 1);
}