一个关于标准转换的问题,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,还是我看漏了?

...全文
1358 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)

64,646

社区成员

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

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