char ** 与char * a[ ] 区别

 先看 char  *a [ ] ;数组

            因为[ ] 的优先级高于* 因此a先和 [ ]结合,他仍是一个数组,数组中的元素才是char * ,前面讲到char * 是一个变量,保存的地址。。3d

            因此 char *a[ ] = {"China","French","America","German"};指针

            同过这句能够看到, 数组中的元素是字符串,那么sizeof(a) 是多少呢,有人会想到是五个单词的占内存中的所有字节数 6+7+8+7 = 28;blog

            可是其实sizeof(a) = 16;内存

            为何,前面已经说到, 字符串常量的本质是地址,a 数组中的元素为char * 指针,指针变量占四个字节,那么四个元素就是16个字节了字符串

            看一下实例:编译器

            #include <stdio.h>io

   int main()
   {
    char *a [ ] = {"China","French","America","German"};
    printf("%p %p %p %p\n",a[0],a[1],a[2],a[3]);
编译

    return 0;
   }变量

能够看到数组中的四个元素保存了四个内存地址,这四个地址中就表明了四个字符串的首地址,而不是字符串自己。。。

      所以sizeof(a)固然是16了。。

      注意这四个地址是不连续的,它是编译器为"China","French","America","German" 分配的内存空间的地址, 因此,四个地址没有关联。

         #include <stdio.h>

   int main()
   {
   char *a [ ] = {"China","French","America","German"};

           printf("%p %p %p %p\n",a[0],a[1],a[2],a[3]); //数组元素中保存的地址
   printf("%p %p %p %p\n",&a[0],&a[1],&a[2],&a[3]);//数组元素单元自己的地址

   return 0;
   }

 能够看到 0012FF38 0012FF3C 0012FF40 0012FF44,这四个是元素单元所在的地址,每一个地址相差四个字节,这是因为每一个元素是一个指针变量占四个字节。。。

       char **s;

       char **为二级指针, s保存一级指针 char *的地址,关于二级指针就在这里不详细讨论了 ,简单的说一下二级指针的易错点。  

       举例:

       char *a [ ] = {"China","French","America","German"};

       char **s =   a;

       为何能把 a赋给s,由于数组名a表明数组元素内存的单元的首地址,即 a = &a[0] = 0012FF38;

       而 0x12FF38即 a[0]中保存的又是 00422FB8 ,这个地址, 00422FB8为字符串"China"的首地址。

       即 *s = 00422FB8 = "China";

         这样即可以经过s 操做 a 中的数据

      printf("%s",*s);

      printf("%s",a[0]);

      printf("%s",*a);

      都是同样的。。。

      但仍是要注意,不能a = s,前面已经说到,a 是一个常量。。

      再看一个易错的点:

      char **s = "hello world";

      这样是错误的,

       由于  s 的类型是 char **  而 "hello world "的类型是 char *

       虽然都是地址, 可是指向的类型不同,所以,不能这样用。,从其本质来分析,"hello world",表明一个地址,好比0x003001,这个地址中的内容是 'h'

  ,为 char 型,而 s 也保存一个地址 ,这个地址中的内容(*s) 是char * ,是一个指针类型, 因此二者类型是不同的。 。。

  若是是这样呢?
  char  **s;

       *s = "hello world";

       貌似是合理的,编译也没有问题,可是 printf("%s",*s),就会崩溃

       why??

      咱来慢慢推敲一下。。

       printf("%s",*s); 时,首先得有s 保存的地址,再在这个地址中找到 char *  的地址,即*s;

      举例:

       s = 0x1000;

      在0x1000所在的内存的单元中保存了"hello world"的地址 0x003001 , *s = 0x003001;

      这样printf("%s",*s);

      这样会先找到 0x1000,而后找到0x003001;

      若是直接 char  **s;

      *s = "hello world";

       s 变量中保存的是一个无效随机不可用的地址, 谁也不知道它指向哪里。。。。,*s 操做会崩溃。。

       因此用 char **s 时,要给它分配一个内存地址。

      char  **s ;

      s = (char **) malloc(sizeof(char**));

      *s =  "hello world";

      这样 s 给分配了了一个可用的地址,好比 s = 0x412f;

      而后在 0x412f所在的内存中的位置,保存 "hello world"的首地址。。

    再如:

    #include  <stdio.h>

   void  buf( char **s)

    {

           *s = "message";

    }

    int main()

     {

        char *s ;

        buf(&s);

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

     }

    二级指针的简单用法,说白了,二级指针保存的是一级指针的地址,它的类型是指针变量,而一级指针保存的是指向数据所在的内存的单元的地址,虽然都是地址,可是类型是不同的

相关文章
相关标签/搜索