令人纠结的两行代码

我的主力博客:半亩方塘

以下内容系原创,转载请务必注明地址

主要参考资料:我在 Stackoverflow 上提的问题 Why
the first is right but the second is wrong ?

这令人纠结的两行代码如下:

const char *cval = "nothing";  // 正确
int *ival = {1, 2, 3, 4};      // 错误  

为什么第一行代码正确第二行代码错误呢?既然 "nothing" 在内存中是以数组的形式存储的,那么,为什么可以定义一个 cval 指向它而不能对应地定义一个 ival 指向下面的数组呢?这确实是一个很让人纠结的问题,看下面的分析吧:

首先我们来看第一行代码:

const char *cval = "nothing";

赋值运算符右侧是一个 字符串字面值常量 ,编译器将字符串字面值常量放在内存空间中的一段连续的地址单元进行存储,且 存储的类型为
const char[] ,存储的形式是: {‘n‘, ‘o‘, ‘t‘, ‘h‘, ‘i‘, ‘n‘, ‘g‘, ‘\0‘} ,这一点很重要,将赋值运算符右侧的字符串字面值赋给左侧的运算对象时,const
char[] 类型将向 const char* 进行转换,由于数组名本身就是一个指针,因此这种转换是合理的,合法的,所以这部分代码是正确的;

再来看看以下的这部分代码:

int *ival = {1, 2, 3, 4}; 

这部分代码怎么是错的了?这是因为,编译器不允许单独将
{1, 2, 3, 4} 存储到内存中,而必须将其拷贝到某一个对象对应的连续的地址单元,显然,赋值运算符右边只是一个指向 int 的指针类型,不具备存储 {1, 2, 3, 4} 的条件,所以,这部分代码是错误的。

由于在 C 语言中,从 C99 以后,有一个称之为
compund literal 的特性,所以对于第 2 行的代码,在 C 中我们可进行如下修改使其正确:

int *ival = (int []) {1, 2, 3, 4};  

上面的这行代码在 C++ 中是不成立的,有错误产生,想想为什么呢?这是因为
C 和 C++ 的语言特性是不一样的,在 C 中,上面代码中的赋值运算符右侧是一个持久的值,是一个常量对象,它被创建的时候有着持久的地址,但是,在 C++ 中,右侧运算对象只是一个临时对象,不具备持久的地址,在 (int
[]) {1, 2, 3, 4}
 这个表达式结束时地址已经消亡,我个人认为,这是
C 和 C++ 语言 右值 规范上的差别,对于这点理由欢迎提供不同参考意见。

令人纠结的两行代码,布布扣,bubuko.com

时间: 2024-10-16 12:10:40

令人纠结的两行代码的相关文章

eImage(仅两行代码实现输出从数据库中查询到的二进制字段)标签

功能: 专门用于向浏览器输出从数据库中查询到的二进制字段.支持通用的几十种文件类型 别名为edoc 使用方法: <chtml><eimage id=书包名type=类型>key</eimage></chtml>或 <chtml><edocid==书包名 type=类型>key</edoc></chtml> ·        id:书包名.ESql标签返回的书包名称 ·        type:类型.输出文件类型

jquery两行代码实现侧边栏三级折叠菜单

jquery两行代码实现侧边栏三级折叠菜单 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="js/jquery-2.1.1.min.js"></script> </head> <bod

iOS 两行代码解决数据持久化

在实际的iOS开发中,有些时候涉及到将程序的状态保存下来,以便下一次恢复,或者是记录用户的一些喜好和用户的登录信息等等. 这就需要涉及到数据的持久化了,所谓数据持久化就是数据的本地保存,将数据从内存中迁入到存储器上.网上有很多种数据持久化的方法,如实现自己实现I/O.数据库.云或则走第三方接口等等.但是有时候可能只是进行一些简单的数据存储,如用户的偏好设置.用户的sessionID等等,这时候使用上述方法便显得有点兴师动众了,现在需要一种更加轻量化的操作方式. 一.认识 NSUserDefaul

iOS网络缓存扫盲篇--使用两行代码就能完成80%的缓存需求

iOS网络缓存扫盲篇 --使用两行代码就能完成80%的缓存需求 下篇预告:使用80%的代码来完成剩下的20%的缓存需求 .敬请 star (右上角)持续关注. 目录 当我们在谈论缓存的时候,我们在谈论什么? GET网络请求缓存 80%的缓存需求:两行代码就可满足 控制缓存的有效性 文件缓存:借助ETag或Last-Modified判断文件缓存是否有效 Last-Modified ETag 总结 一般数据类型借助 Last-Modified 与 ETag 进行缓存 剩下20%的网络缓存需求--真的

【转】Delphi+Halcon实战一:两行代码识别QR二维码

Delphi+Halcon实战一:两行代码识别QR二维码 感谢网友:绝代双椒( QQ:51536348)的支持 本文是绝代双椒的作品,因为最近在忙zw量化培训,和ziwang.com网站的升级,halcon没时间操作. 不过,随着国内产业升级,机器人行业的发展,Delphi+Halcon的未来,是无可限量的. 其他网友,有halcon这方面作品的,有需要,也可以交给zw转发. 另外,zw正在争取培训机构合作,开办Delphi+Halcon方面的培训的项目,有兴趣的机构可以联系QQ:3578117

两行代码搞定MFC清屏功能

MFC清除屏幕功能 不少人在使用MFC显示图像都遇到过解决清除屏幕的问题,网上有不少解决方案,但是这些方案都不是很简单,最近本文也遇到了同样的问题,因此对MFC的显示原理进行了深入的研究,找到了最简单的解决方案: (1)获取控件的句柄 (2)调用showWidnow(FALSE). (3)调用showWindow(TRUE); 两句简单的代码轻松搞定MFC清除屏幕功能! 代码如下: void CClearScreenMFCDlg::OnBnClickedLoadImage() { // TODO

iOS两行代码实现动态缓存 cell 的高度

在我们的日常开发中要经常动态缓存 cell 的高度,每当这个时候我们都要手动去根据文字内容计算高度,显得啰嗦又麻烦,这里我利用 xib 来快速的实现这个效果 第一步 利用 xib 来创建我们自定义的 cell. 自定义 cell 的布局 如上图,是我自定义的 cell 布局,从图中可以看出我们要想动态缓存 cell 的高度唯一要解决的就是动态计算标红 label 的高度就 OK 了. 第二步 设置 Label 的属性, Label 换行属性 给 Label 添加约束 选中我们的正文 Label

漂浮广告代码兼容ie、firefox,多个漂浮不冲突,调用只需两行代码

原文:漂浮广告代码兼容ie.firefox,多个漂浮不冲突,调用只需两行代码 将广告内容放在div中,设置一个id,然后用下面方法调用var adcls=new AdMove("div的id");adcls.Run();注意,在调用前要先引用Main.js和AdFloat.js,div也要在调用前写好,原因就不用说了吧或者也可以用下面方法,在页面加载完成时调用,就不用考虑位置了addEvent(window,"load",initad);function inita

震惊!Vector两行代码求逆序对,六行代码过普通平衡树

Vector两行代码求逆序对 背景:济南集训Day7上午T2,出了一道逆序对的裸题,SB的我没看出是逆序对来,于是现场推了一个很刁钻的求逆序对的方法 首先我们想一下冒泡排序的过程,我们不难发现,对于每一个元素,我们实际上是让他不停的和前面的元素比较,交换. 也正是因为这个过程决定了在冒泡排序的过程中:一个位置的数的前面的数一定是递增的(从小到大排的话) 那么我们在交换的时候,直接二分找到一个合适的位置,插入即可 这个很显然可以用平衡树Vector实现 代码也非常短, 1 #include<cst