博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c语言char aa 1000,char ** 与char * a[ ] 区别
阅读量:6360 次
发布时间:2019-06-23

本文共 2269 字,大约阅读时间需要 7 分钟。

先看 char  *a [ ] ;

由于[ ] 的优先级高于* 所以a先和 [ ]结合,他还是一个数组,数组中的元素才是char * ,前面讲到char * 是一个变量,保存的地址。。

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

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

但是其实sizeof(a) = 16;

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

看一下实例:

#include

int main()

{

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

printf("%p %p %p %p\n",a[0],a[1],a[2],a[3]);

return 0;

}

b78b6013964eab92b043a993d8a19d51.png

可以看到数组中的四个元素保存了四个内存地址,这四个地址中就代表了四个字符串的首地址,而不是字符串本身。。。

因此sizeof(a)当然是16了。。

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

#include

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;

}

4cb96e83b053b6e3a80f9e9664bb1107.png

可以看到 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 

void  buf( char **s)

{

*s = "message";

}

int main()

{

char *s ;

buf(&s);

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

}

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

转载地址:http://onima.baihongyu.com/

你可能感兴趣的文章
在PowerDesigner中设计物理模型1——表和主外键
查看>>
NYOJ58最少步数
查看>>
从数据库中查询数据
查看>>
2012年12月桌面日历壁纸免费下载——美女主题壁纸
查看>>
WPF Effect Clip以及Transform
查看>>
Change font size quickly
查看>>
.NET深入解析LINQ框架(五:IQueryable、IQueryProvider接口详解)
查看>>
python基于http协议编程:httplib,urllib和urllib2
查看>>
一刻钟精通正则表达式
查看>>
linux sed命令详解
查看>>
JavaScript之对象
查看>>
1 使用 CXF 和 Spring 创建 Web 服务
查看>>
oracle xml类型字段的索引
查看>>
简单演示 Oracle 数据库并发导致行级锁
查看>>
非阻塞socket调用connect, epoll和select检查连接情况示例
查看>>
《黑客与画家》读书笔记一
查看>>
演示热块——表数据块
查看>>
Zebra命令模式分析(二)[补]
查看>>
Windows操作系统---C Drive
查看>>
TDSS 0.0.2 测试版发布,分布式存储系统
查看>>