该篇与上篇衔接
二维数组
int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));//48   3*4*sizeof(int)
	printf("%d\n", sizeof(a[0][0]));//4   第一行第一个元素  就是整形大小
	printf("%d\n", sizeof(a[0]));//16
	//a[0]就可以理解为 第一行数组名 
	//sizeof(a[0])数组名a【0】单独放在sizeof内部 a【0】表示整个第一行
	//sizeof(a[0])计算的就是第一行的大小
	printf("%d\n", sizeof(a[0]+1));//4/8  符合sizeof规则第三条 所以他叔第一行第一个元素的地址
	printf("%d\n", sizeof( * (a[0] + 1)));//4     第一行第二个解引用 , 的到元素
	printf("%d\n", sizeof(a+1));//4/8   对于二维数组来说 首元素就是第一行
	printf("%d\n", sizeof(*(a+1)));//16   *(a+1)->a[1]
	printf("%d\n", sizeof(&a[0]+1));//  4/8
	printf("%d\n", sizeof(*(&a[0] + 1)));// 16
	printf("%d\n", sizeof(*a));// 16    a是代表整个数组  *a 代表的是对第一行解应用 得到的是第一行的数组
	printf("%d\n", sizeof(a[3]));//16  既然a[3]存在它的类型就是int()[4] 假象他是一个第四行
	
	return 0;
}
int main()
{
	short s = 5;
	int a = 4;
	printf("%d", sizeof(s = a + 6));//2   最后的结果由short而定  short2个字节。sizeof内部表达式不参与运算
	printf("%d", s);//5
	return 0;
}
第三个解析
 
指针笔试题
int main()
{
    int a[5] = { 1, 2, 3, 4, 5 };
    int *ptr = (int *)(&a + 1);
    printf( "%d,%d", *(a + 1), *(ptr - 1));
    return 0;   //第一个打印:a的地址没变 指向一 加一指向2的地址
}
//程序的结果是什么?
//2  5
解析
 
//由于我还没介绍过结构体,这里告知结构体的大小是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);//相当于p+1   加1跳过一个类型 结构体类型20个字节直接跳过所以是加20  0x100000+20=0x100014   4成16的0次方。。。
	printf("%p\n", (unsigned long)p + 0x1);//0x100001   正数加1就是1  不跟指针一样
	printf("%p\n", (unsigned int*)p + 0x1);//0x100004    +4  一个整形字节
	return 0;
}
int main()
{
    int a[4] = { 1, 2, 3, 4 };
    int* ptr1 = (int*)(&a + 1);
    int* ptr2 = (int*)((int)a + 1);// a转化为整形  一个整形4个字节   加1是加一个字节
    printf("%x,%x", ptr1[-1], *ptr2);
    return 0;
}

 
 %x打印打印16进制 只打印有效数组所以结果为4 2000000
#include <stdio.h>
int main()
{
    int a[3][2] = { (0, 1), (2, 3), (4, 5) };
    int* p;
    p = a[0];
    printf("%d", p[0]);
    return 0;
}
解析
#include <stdio.h>
int main()
{
    int a[3][2] = { (0, 1), (2, 3), (4, 5) };//用了小括号表示是逗号表达式  相当于就放了{1,3,5}第一行放了1  3  第二行5 0 第三行00
    int* p;
    p = a[0];//没有& 也没放在sizeof内部 所以他代表首元素地址  1 放到了整形指针
    printf("%d", p[0]);//结果1      *(p+0)
    return 0;
}//a[0]表示第一行,然后没有&,也没有sizeof,所以是首元素,加起来就是a[0]这一行的首元素
int main()
{
    int a[5][5];
    int(*p)[4];
    p = a;//int (*)[5]
    printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
    //?
    return 0;
}
int main()
{
    int a[5][5];
    int(*p)[4];
    p = a;//int (*)[5]
    printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
    //&p[4][2] 可以理解为 (*(p+4)+2)  解引用相当于从当前位置访问一个数组  刚好int四个 然后加2
    return 0;
}
**结果FFFFFFFC,4 **
C是12
//&p[4][2] 可以理解为 (*(p+4)+2) 解引用相当于从当前位置访问一个数组p[4] 刚好int四个 然后加2
 
 指针-指针 得到指针见的元素个数
 
 因为地址由低到高变化小地址减去大地址所以是-4
-4以%d打印就是-4 认为内存里放的有符号整数 以%p打印认为内存里是个地址 所以将地址补码直接拿出来 因为%p所以以16进制书写 4个1是一个f如下
 - 4 写到内存就是
 10000000000000000000000000000000100
 111111111111111111111111111111111111011
 111111111111111111111111111111111111100
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;
}
int main()
{
    int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    int* ptr1 = (int*)(&aa + 1);//10   赋给ptr1的时候他就是个整形了  下面的-1是减去一个整形  所以打印10
    int* ptr2 = (int*)(*(aa + 1));//5  对第二行解引用拿到第二行  拿到第二行相当于拿到数组名。可以写成aa[1]  他就是6的地址 本身是个整形在解引用整形无意义
    printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
    return 0;
}
#include <stdio.h>
int main()
{
	char* a[] = { "work","at","alibaba" };
	char** pa = a;
	pa++;
	printf("%s\n", *pa);
	return 0;
}

int main()
{
	char* a[] = { "work","at","alibaba" };//数组名表示首元素地址  首元素地址表示char*   
	char** pa = a;//相当于pa指向第一个的char*
	pa++;//指向“at”的char*   pa指向数组,+1指向下一个元素
	printf("%s\n", *pa);//解引用at  从这里向后打印字符串
	return 0;
}//at
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);
	return 0;
}


第一次解引用拿到c+2 第二次拿到了 char*内容 所以打印 POINT

printf("%s\n", *-- * ++cpp + 3);//++优先级高   --就是对c+1  减去1 后变成c 如果是c 指向位置也会发生改变 再解引用拿到 ENTER 加3 指向T。从E向后打印打印结果ER
*cpp[-2]可以写成 **(cpp-2) +3指向R打印ST
 
printf("%s\n", cpp[-1][-1] + 1);//cpp[-1][-1] 可以写成 (*(*(cpp-1)-1)+1   结果EW

总体打印结果POINT ER ST EW



















