博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++类型小记
阅读量:6813 次
发布时间:2019-06-26

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

最近在项目中遇到一个很有意思的问题。简单重现一下,大概是如下情况。

在文件f1.cpp中定义字符串

char str[16] = "abcdefg";

在其他文件中,比如f2.cpp中使用extern进行一下声明

extern char *str;

在对str进行操作时,比如最简单的

void func(){    cout << str << endl;}

这时候竟然出现了"段错误"Segmentation fault

其实单抓出来我们都能发现问题,但是在一个庞大的项目中,这种细枝末节并没那么显眼(当然这个代码不是我写的,坑不是我挖的,我不管就是不是我的错,逃)

分析

上面的问题其实很简单,在f2.cpp中str被声明为了char *,而在str被定义的f1.cpp中,str的类型是char[]。这就是问题所在了。

可能很多人会忽略这种小问题,或者"觉得char[]char*有什么区别?不都一样用吗?"

虽然大多数情况下,在同一个文件中对char[]char*操作好像没有什么不同,

比如

char str[16] = "aaa";cout << arr << endl;//传参等等

那是因为在同一个文件中,如果你对变量名操作,编译器会直接取用其地址而让你产生错觉,不过我们也能看出端倪

char str[16] = "aaa";char *pstr = str;//32位sizeof(str);    //16sizeof(pstr);   //4

回到刚才的问题,那么为什么在同一个文件中很正常的操作到了跨文件时就出现了异常呢?

其实很简单,我们调试一下就知道,这里我用的是VisualStudio,

在同一个文件中时

str    0x0034f988 "aaa"    char[16]pstr   0x0034f988 "aaa"    char *

可以看到我们定义pstr时是直接正确的将str这个字符串的地址给赋值给了pstr,这一切就很合理了。

这时候我们再回来看在不同文件时的情况

str    0x64636261 "读取字符串时出错"    char*

地址一看就不对,字符串常量值应该在只读常量区的,这么高的地址肯定是错的,但是为什么会出现这个地址呢?仔细看一下,这个地址有点奇怪64 63 62 61?

看一下ASCII表,16进制对应的字符分别是d c b a, 但是为什么会取到这个值呢?

这里就牵扯到编译的问题了,编译器在编译文件f1.cpp的时候,将str名字及其地址加入符号表;

在编译文件f2.cpp的时候,由于str只是声明,而符号表中确实能找到str及其地址,编译链接顺利通过没有任何问题。但是到了运行的时候,再f2.cpp中使用str的名字进行寻址,从而顺利找到f1.cpp中str的首地址,但是问题出现了,这里我们声明的str类型是char *,这个指针的值是什么呢?

指针变量的地址有了,值当然就是这个地址开始取4个字节的值了,结果顺利取到x64636261。在f2.cpp中把声明类型改为extern char str[];就没有任何问题了。

也许有人会问“既然如此,地址不应该是0x61626364吗?”

关于这个问题的话,,因为我的机器是小端的


到这里这个问题的缘由就解释清楚了,也警示了我们平时开发过程中对细节的重视要加强,这里再次重申

[]类型和*类型不是同一种类型!!!!!!!

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

你可能感兴趣的文章
快如闪电、超轻量级的基于.Net平台的依赖注入框架Ninject
查看>>
Nginx+upstream针对后端服务器容错的运维笔记
查看>>
使用SQL_TRACE进行数据库诊断
查看>>
SQL Server 中心订阅模型(多发布单订阅)
查看>>
Vue父组件接收不到子组件$emit事件的原因分析
查看>>
工作总结的字体和格式要求
查看>>
CentOS 6.9永久设置静态路由表以及路由表常用设置
查看>>
解决Docker时区与主机时区不一致的问题
查看>>
思考与知识
查看>>
访问日志不记录静态文件 访问日志切割 静态元素过期时间
查看>>
idea中复制module和module中的蓝色tag出现的方法
查看>>
python中的面相对象
查看>>
Spring缓存注解@Cache使用
查看>>
去除wordpress的category各方法对比
查看>>
traceroute
查看>>
精通汇编语言,有兴趣一起搞破解的请进!
查看>>
C#缺省参数可以让代码变得更加简洁明了与时俱进心里敞亮了很多了
查看>>
【自然框架】js版的QuickPager分页控件 V2.0
查看>>
poj-2049 Finding Nemo *
查看>>
模块化编程本质探讨
查看>>