一个关于标准转换的问题,supermegaboy等请进

FrankHB1989 2011-11-16 12:35:50
原问题:http://tieba.baidu.com/p/1285092826
现在的问题是我不清楚我的解释是否完全正确。
我找过N3290全文的array-to-pointer conversion出现的地方;3.10;以及Clause 5的所有conversion和rvalue出现的地方,但没有发现ISO C++保证内建操作符在哪些确定情况下应用这些lvalue transformation。这样,按ISO C++(C++03也一样)就无法完全解决这里的问题——如何断定表达式"12"+12是合法的。
是ISO C++的defect,还是我看漏了?

...全文
1503 60 打赏 收藏 转发到动态 举报
写回复
用AI写文章
60 条回复
切换为时间正序
请发表友善的回复…
发表回复
FrankHB1989 2013-01-25
  • 打赏
  • 举报
回复
非故意挖坟。 有人指出了一个相关问题: https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/sjK_KoeD3xo 注意到这里的规则只是指出了类型的要求,还是有点不自然的地方。对于array-to-pointer conversion(以及funtion-to-pointer conversion),转换前后type显然保证是不同的,所以没问题;但对于lvalue-to-rvalue conversion,情况就不一样了(volatile的lvalue转换为rvalue影响ovservable behavior),尽管内建类型非左值始终是cv-unqualified,但C++允许cv-qualified class type prvalue,这样转换过程中类型可以表现为不变,不见得适用这条规则。 偏偏要命的是ISO C++连value和prvalue的关系都没明确(ISO C好歹吱了声rvalue是value同义词),更不用说value computation是不是会导致需要prvalue了……
ken_scott 2012-12-02
  • 打赏
  • 举报
回复
重温这个贴子觉得很兴奋,高手云集,特别是标准界理论派第一高手S 和 标准界实践派第一高手J的精彩辩论 对我而言现在唯一可确定的是:"12"+12是未定义的,在<<Exceptional C++>>上看到的 合法的只有:"12"+0, "12"+1, "12"+2, "12"+3 我认为:LZ是标准界理论派的第二高手,哈哈 都是值得我学习的榜样,哎,相去甚远啊
zanglengyu 2011-11-20
  • 打赏
  • 举报
回复
类型提升问题,里边又不是数组,sizeof取的是类型的字节数,32位机上string默认四字节,int型也是,DEV-CPP编译器是支持标准的C++编译器,我得结果都是4
smartgotodo 2011-11-19
  • 打赏
  • 举报
回复
没有意义的争论
机智的呆呆 2011-11-18
  • 打赏
  • 举报
回复
[Quote=引用 55 楼 jinhao 的回复:]
仔细考虑了一下, 是未定义的。这样得到的地址完全有错误的。也就是说 "12" + 12 - 12 完全有可能不是指向"12"的首地址。
[/Quote]
Jinhao 2011-11-17
  • 打赏
  • 举报
回复
好像没说清楚.
它不是未定义,是从overflow的行为来说的.与值无关.

"12" + 12 是否合法得依据编译器判断是否有溢出.也就是well-formed,与是否undefined behavior无关.
其次sizeof("12" + 12) 这是合法的.表达式的值的类型是const char*, 表达式不求值,因此也不会发生溢出.

另外一点,一来就贴大片的标准,来证明自己的观点,这做法是错误的.因为标准也不一定正确
Jinhao 2011-11-17
  • 打赏
  • 举报
回复
见最后:

If both the pointer operand and the result point to elements of the same array object, or one past the last element
of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.

这里的undefined意思是指这个表达式evaluation是否会overflow是undefined. 并非指值是undefined的,很明显,值是implementation-defined

另外,它不是未定义的,是因为那是一个常量表达式
If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined, unless such an expression is a constant expression(5.19), in which case the program is ill-formed.
机智的呆呆 2011-11-17
  • 打赏
  • 举报
回复
这帖子生命力很顽强啊~~百足之虫,死而不僵~~
FrankHB1989 2011-11-17
  • 打赏
  • 举报
回复
[Quote=引用 46 楼 jinhao 的回复:]

引用 41 楼 supermegaboy 的回复:

请留意,overflow与otherwise之间是一个分号。

还是请注意,标准是C/C++世界的法律,虽然像现实世界的法律一样标准也在不断地修订,但一旦制定好了,她就是行为准则。

如果你认为标准是错误的,那么,你用什么来证明你是错误还是正确呢?标杆都没有了,就像物理世界中失去了相对物体,这世界就会乱了。

认为标准错误的人……
[/Quote]
你需要指出为什么"12" + 12是常量表达式就不适用5.7中的条款。
另外:
ISO C++11
5.19/1... [ Note: Constant expressions can be evaluated during translation.—end note ]
似乎也没保证一定会在运行期完成求值的行为,或者是否溢出一定要在编译期判断。
Jinhao 2011-11-17
  • 打赏
  • 举报
回复
[Quote=引用 41 楼 supermegaboy 的回复:]

请留意,overflow与otherwise之间是一个分号。

还是请注意,标准是C/C++世界的法律,虽然像现实世界的法律一样标准也在不断地修订,但一旦制定好了,她就是行为准则。

如果你认为标准是错误的,那么,你用什么来证明你是错误还是正确呢?标杆都没有了,就像物理世界中失去了相对物体,这世界就会乱了。

认为标准错误的人,只能证明他是错误的!
[/Quote]

已经两次提到"12" + 12是常量表达式。要么well-formed,要么ill-formed,没有undefined



FrankHB1989 2011-11-17
  • 打赏
  • 举报
回复
好吧,算我用词不当……?
合法即legal,我指的是syntactically correct。另外,"12"+12不止合乎语法,也满足可诊断语义规则,和ODR也没关系,实际上是well-formed(按数理逻辑的翻译可以是“合式”的,不过还是原文好了……),这和它的确会产生undefined behavior不矛盾。

Jinhao 2011-11-17
  • 打赏
  • 举报
回复
仔细考虑了一下, 是未定义的。这样得到的地址完全有错误的。也就是说 "12" + 12 - 12 完全有可能不是指向"12"的首地址。
FrankHB1989 2011-11-17
  • 打赏
  • 举报
回复
[Quote=引用 32 楼 jinhao 的回复:]

>>那为什么就不在一个地方干脆地写明白呢?

— When used as operands of operators. The operator’s requirements for its operands dictate the destination type (clause 5).

觉得这句写明白了吗?也同样没有说明数组往指针的转换。最关键的是没有对数组做operator+的……
[/Quote]
这句虽然没在和array-to-pointer conversion同一个地方写明白,但写在Clause 4的顶层,对于各个standard conversion sequence都适用,还算清楚。之前是我看走眼,我认了。
FrankHB1989 2011-11-17
  • 打赏
  • 举报
回复
[Quote=引用 41 楼 supermegaboy 的回复:]
认为标准错误的人,只能证明他是错误的!
[/Quote]
这倒未必。法律也需要修订。否则就没必要有defect report这回事了。

机智的呆呆 2011-11-17
  • 打赏
  • 举报
回复
[Quote=引用 40 楼 jinhao 的回复:]
好像没说清楚.
它不是未定义,是从overflow的行为来说的.与值无关.

"12" + 12 是否合法得依据编译器判断是否有溢出.也就是well-formed,与是否undefined behavior无关.
其次sizeof("12" + 12) 这是合法的.表达式的值的类型是const char*, 表达式不求值,因此也不会发生溢出.

另外一点,一来就贴大片的标准,来证明自己……
[/Quote]
俺同意sizeof("12" + 12)是合法的,但"12"+12是未定义的。
飞天御剑流 2011-11-17
  • 打赏
  • 举报
回复
请留意,overflow与otherwise之间是一个分号。

还是请注意,标准是C/C++世界的法律,虽然像现实世界的法律一样标准也在不断地修订,但一旦制定好了,她就是行为准则。

如果你认为标准是错误的,那么,你用什么来证明你是错误还是正确呢?标杆都没有了,就像物理世界中失去了相对物体,这世界就会乱了。

认为标准错误的人,只能证明他是错误的!
FrankHB1989 2011-11-17
  • 打赏
  • 举报
回复
[Quote=引用 51 楼 jinhao 的回复:]

"12" + 12。不考虑是不是常量表达式,标准说,这表达式是undefined behavior。并非指其值是undefined,而是指所指向的元素是undefined。
the evaluation shall not produce an overflow; otherwise, the behavior is undefined.
这段话中的overflow也不是指指针的值溢出,而是……
[/Quote]
这又有问题了。
undefined behavior首先是behavior。bahavior是什么?ISO C++没说,或许认为是不言自明的。引用ISO C的略作参考:
ISO C99
3.4
1 behavior
external appearance or action
很显然,如果C++所说的behavior是这个意思,那么说表达式是undefined behavior说不通。而所谓undefined(大意是表示“this International Standard imposes no requirements”),我似乎从来没看到用来修饰一个值的状态的,访问某个对象得到值之类的behavior倒是可以讨论是否undefined。这大概是因为undefined表示错误的东西,值有没有都无所谓。(而unspecified一词倒有unspecified bahavior和unspecified value的用法;indeterminate只修饰value,不修饰behavior)。
那么“所指向的元素是undefined”该做何解?"12" + 12的求值并没有访问元素。
最后。
behavior没有限定是conforming implementation还是program。判定undefined behavior是否存在,并不是语言实现的任务。
因此:
T * buf = new T[10];
T * p = buf + 5;
这里可能有undefined behavior,当你说的情况成立时。尽管理论上可以把这种情况作为ill-formed处理要求实现提供diagnose,不过可能代价太高所以没这么规定。
更极端的例子:像*new(nothrow) int;在运行时会不会有undefined behavior,根本无法在编译期确定。

机智的呆呆 2011-11-17
  • 打赏
  • 举报
回复
最后。
T * buf = new T[10];
T * p = buf + 5;
能保证p指向buf的第6个元素? 很明显不能。可以对类型T重载operator new[]。
如果说buf引用的不是数组。根据上面的分号和otherwise,那buf+5就是未定义的?

俺的理解,根据标准就是未定义。
机智的呆呆 2011-11-17
  • 打赏
  • 举报
回复
[Quote=引用 51 楼 jinhao 的回复:]
"12" + 12。不考虑是不是常量表达式,标准说,这表达式是undefined behavior。并非指其值是undefined,而是指所指向的元素是undefined。
the evaluation shall not produce an overflow; otherwise, the behavior is undefined.
这段话中的overflow也不是指指针的值溢出,而是指……
[/Quote]
"12" + 12未定义的原因:

Question 6.17
Here's a neat trick: if I write
int realarray[10];
int *array = &realarray[-1];
I can treat array as if it were a 1-based array.

Although this technique is attractive (and was used in old editions of the book Numerical Recipes in C),it does not conform to the C standards. Pointer arithmetic is defined only as long as the pointer points within the same allocated block of memory, or to the imaginary ``terminating'' element one past it; otherwise, the behavior is undefined, even if the pointer is not dereferenced. The code above could fail if, while subtracting the offset, an illegal address were generated (perhaps because the address tried to ``wrap around'' past the beginning of some memory segment).

References: K&R2 Sec. 5.3 p. 100, Sec. 5.4 pp. 102-3, Sec. A7.7 pp. 205-6
ANSI Sec. 3.3.6
ISO Sec. 6.3.6
Rationale Sec. 3.2.2.3

选自comp.lang.c Frequently Asked Questions
Jinhao 2011-11-17
  • 打赏
  • 举报
回复
"12" + 12。不考虑是不是常量表达式,标准说,这表达式是undefined behavior。并非指其值是undefined,而是指所指向的元素是undefined。
the evaluation shall not produce an overflow; otherwise, the behavior is undefined.
这段话中的overflow也不是指指针的值溢出,而是指超出数组范围。指针不是integer,没有overflow一说。

因此,我在最上面说了"12"[12]和*("12" + 12)是未定义的。这里,解引用操作是undefined.

If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined, unless such an expression is a constant expression(5.19), in which case the program is ill-formed.
"12" + 12 是不是constant expression?跟can be evaluated没关系

但从语义上说"12" + 12是不正确的,因为数组总共就三个元素。但是单独考虑其值的话,是完全正确的,野指针也表示地址,也指向某个对象,而且没有依赖不确定的值,但该值是unspecified。

最后。
T * buf = new T[10];
T * p = buf + 5;
能保证p指向buf的第6个元素? 很明显不能。可以对类型T重载operator new[]。
如果说buf引用的不是数组。根据上面的分号和otherwise,那buf+5就是未定义的?

加载更多回复(38)
源码直接下载地址: https://pan.quark.cn/s/1c143f32ee83 华为作为全球领先的通信设备供应商,其产品系列广泛涉及各类网络设备,其中包括我们接下来要探讨的上网卡产品。华为上网卡驱动程序是一种专门为华为品牌旗下多种型号上网卡开发的软件模块,其主要功能在于保障这些设备与计算机操作系统的无缝对接。涉及的型号涵盖EC8189、EC226、EC169C、EC360、EC1260、EC1261、EC189、EC122、EC150以及EC168,这些均是由华为公司推出的移动宽带调制解调器,旨在通过移动网络实现便捷的互联网接入服务。驱动程序在计算机系统中的地位举足轻重,它充当了硬件设备与操作系统之间的媒介,负责对硬件设备发出的指令行解读和执行,并将操作系统的指令传递给硬件设备。华为上网卡驱动程序的及时更新和精准安装是保障设备稳定运作和性能达到最优的关键因素。"天翼宽带安装程序V1.3.3.exe"是由中国电信提供的一个整合性软件包,内含华为上网卡的驱动程序及配套的管理工具。用户可借助此安装程序来执行华为上网卡的相关驱动安装及更新,同步享受中国电信的3G或4G网络服务。版本标识V1.3.3代表软件经过迭代优化,通常包含了对错误的修正、性能的改善以及新功能的引入。 "SetupInfo.xml"作为安装程序的配置文档,其中收录了安装流程中的各项设定和元数据信息,例如安装流程、文件定位、依赖条件等。它是安装程序在执行时参照和遵循的纲领,旨在确保安装流程按既定方案行。文件名"CT_HW_EVDO_Driver"或许指向华为的EVDO(Evolution-Data Optimized)驱动程序,EVDO是一种3G无线通信规范,具备高速数据传输的特性。该驱动可...
内容概要:本文围绕【博士论文复现】基于小信号扫频辨识的光伏并网逆变器正负序交互稳定性分析展开,结合Matlab代码与Simulink仿真实现,系统研究了光伏并网逆变器在弱电网环境下的正负序阻抗建模与交互稳定性问题。重点采用小信号扫频法行系统辨识,获取逆变器的正负序阻抗特性,并通过奈奎斯特稳定判据等方法分析其在不同电网强度下的稳定性表现。文中详细阐述了扫频激励信号的设计原理、频域响应数据的提取与处理流程、阻抗模型的拟合与验证方法等关键技术环节,实现了对逆变器在复杂电网条件下动态交互行为的精确刻画。该研究不仅深入揭示了新能源并网系统中潜在的宽频振荡机理,也为提升系统稳定性、优化控制器设计提供了坚实的理论依据和有效的技术手段。; 适合人群:具备电力电子、自动控制及电力系统基础知识,从事新能源并网、电力系统稳定性研究的研究生、科研人员及工程技术人员。; 使用场景及目标:① 掌握基于小信号扫频法的电力电子装置阻抗建模方法;② 深入理解光伏并网逆变器在弱电网下的正负序交互稳定性机理;③ 学习并复现高水平博士论文中的核心仿真技术,提升科研实践能力;④ 为实际工程中新能源并网系统的稳定性分析、振荡问题诊断与控制器优化设计提供理论支持和技术参考。; 阅读建议:学习者应结合提供的Matlab代码与Simulink模型,深入理解扫频辨识的原理与实现步骤,重点关注锁相环、电流控制环等关键模块对系统阻抗特性的影响,并尝试改变系统参数以观察稳定性变化,从而加深对理论知识的掌握。
代码转载自:https://pan.quark.cn/s/a4b39357ea24 OPC(OLE for Process Control)是由微软推出的一种应用于工业自动化场景下的数据交换规范,其目的是使多样化的自动化装置与软件平台之间能够实现信息互通。在本项研究中,我们集中探讨的是一个运用C#语言构建的完整OPC客户端的源代码实现。该客户端具备与OPC服务器建立连接、获取或设置数据的能力,从而促成设备间的协同工作。鉴于C#是.NET框架的核心编程语言,并且拥有丰富的类库资源及强大的面向对象支持,它特别适合用于开发此类工业环境的应用程序。接下来将针对OPC客户端源代码中可能涉及的核心技术要点行详尽的阐述: 1. **OPC Foundation .NET库**:为了在C#环境下实现OPC通信功能,开发人员通常会选择采用OPC Foundation提供的.NET库,例如OPC-UA .NET Standard或OPC Classic .NET。这些库提供了操作OPC服务器的必要API,涵盖了建立连接、遍历服务器节点、读取与写入数据等一系列操作。 2. **OPC连接配置**:客户端在运行前必须先与OPC服务器建立通信通道。这一过程通常需要配置服务器的位置信息、身份验证凭证(包括用户名和密码)以及连接的详细参数。在源代码中,可能会包含一个`Connect()`方法来处理这些连接细节。 3. **数据项订阅机制**:OPC客户端通过向服务器订阅数据项来实时获取数据更新。在订阅阶段,客户端会指定需要监控的数据项的唯一标识,并设定当数据发生变化时触发的回调函数。在C#编程语言中,这一过程可能通过`AddSubscription()`和`AddItem()`方法来完...

65,211

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧