//定义一个指针变量 , 和定义整型变量类似,也包括三部分:数据类型 变量名 =  初值
    //只不过指针变量用来存储地址而已.
    //int  * 指针变量类型 , p 指针变量名 , NULL 指针变量初值.
    //int  的作用 : 1,当自增时增加几个字节,2,当存取数据时一次性读取几个字节.
    // 定义时 , * 告诉编译器,后面的变量是一个指针变量;
   
    int  * p = NULL ;
    
    //指向关系
    p = &a;  //将a 的地址赋值给p .
    
    printf("%d\n", a);  //直接访问 内存单元数据
     // * p 此时的作用是根据指针变量存储的地址,找到对应的内存单元,将内存单元上的数据读取出来.
    
    printf("%d\n", *p); //间接访问 /间接访问内存单元数据
    
    * p =20 ;
    printf("%d\n", a);
    printf("%d\n", *p);
    //对于指针变量类型,所规定的存储空间的大小只和操作系统有关,32位是4个字节,64位是8个字节.

 int * p1 = NULL;
//    //赋初值为NULL , 让指针变量指向一个无效的空间.
//    //当对p1 指向的空间进行操作时,p1 必须指向一个有效的空间.
//    p1 = & b;
//    *p1 = 50 ;
//     printf("%d\n" , *p1);
//    int c = 30 ;
//    p1 = & c ;
//    //指针变量的重新赋值,我们叫做指针重指向 ,只看最后一次指向.
//    printf("%d\n" , *p1);

    //Incompatible pointer types assigning to 'int * '
    //incompatible 类型不匹配....
    //Thread 1 : EXC_BAD_ACCESS (code = 1 , address = 0x0)
    //没有指向一个有效的空间.  奔溃 crash
    
    
   //指针与数组
//    
//    int a [ 5] = {10,11,12,13,14};
//    
//    int  * p = NULL;
//    //让p指向数组的首地址 (数组名 a 就代表数组的首地址 , 代表数组中第一个元素的地址).
//    p = a;  //
//   // printf("%d \n" , *p);
//  //  p ++ ;
//    for (int i = 0 ; i < 5 ; i ++) {
//        printf("%d  " , *(p + i)); //printf("%d  " , *(a + i));
//    }
//    printf("\n");
//    //当把数组的首地址赋给指针变量p之后,指针变量就可以当做数组名来使用.
//    //数组名是一个常量不可对其更改.


 //指针数组.(数组中的内一个元素都是一个指针变量).
    char str [] = "Frank";
    //字符数组str 需要存储字符,所以把常量区中Frank 字符串的内容拷贝到数组中. 通过数组操作操作的是栈区的内容.
    //而对 数组a 来说,数组中的每一个元素都是一个字符型的指针变量,指针变量用来存储地址,所以将常量区中Frank , Duck ,iPhone 的开始地址拷贝到对应的变量中通过指针操作操作的是常量区的内容.
    char * a [3] = {"Frank","Duck","iPhone"};
     ////常量区的内容不可更改.