来自ptrdiff_t和size_t的奇怪结果 [英] Strange result from ptrdiff_t and size_t

查看:70
本文介绍了来自ptrdiff_t和size_t的奇怪结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

< code>

#include< iostream>


int main(无效)

{

使用命名空间std;


int p [100];

int * p1 = p;

int * p11 = p + 2;

int * p2 = p + 12;


ptrdiff_t pd1 =(p2 - p1)* size_t(p11 - p) +(p2-p1) - (p11-p1);

size_t st1 = 30;


cout<<" ptrdiff pd1 =" << pd1<<",size_t st1 ="<< st1<< endl;

cout<<"(pd1< st1)= "<<(pd1< st1)<< endl;

cout<<"(pd1 - st1)="<<(pd1 - st1) << endl;

cout<<"(st1 - pd1)=" <(st1 - pd1)<< endl;

cout<< endl;


// for(size_t i = 0 ; i< pd1-st1; ++ i)cout<< i<<结束;


返回0;

}

< / code>


àì?á·?±×·¥à? ???°à°ú'? 'ùà?°°°?''''。


< code>

ptrdiff pd1 = 34,size_t st1 = 30
(pd1< st1)= 0

(pd1 - st1)= 4

(st1 - pd1)= 4294967292

< / code>


比较pd1不小于st1; pd1应该大于

st1。但是,减号操作的结果是相反的。


这不是化妆代码,而是在编写程序时遇到的问题。

C ++标准库容器有一个size()成员函数

返回size_t,这是一个无符号类型,并且随机访问迭代器之间的减法两个

类型。使用这些值,一些for循环出错了

意外。


我使用的编译器如下。


< code>

使用内置规格。

目标:i486-linux-gnu

配置:../ src / configure -v --enable-languages = c,c +

+,fortran,objc,obj-c ++,treelang --prefix = / usr --enable-shared --with-

system-zlib --libexecdir = / usr / lib --without-included-gettext --enable-

threads = posix --enable-nls --program-suffix = -4.1 --enable -__ cxa_atexit

--enable-clocale = gnu --enable-libstdcxx-debug --enable-mpfr --with-

tune = i686 - -enable-checking = release i486-linux-gnu

线程模型:posix

gcc版本4.1.2 20061115(预发布)(Debian 4.1.1-21)

< / code>


谢谢,


Ahn,Ki Yung

解决方案

ky****@gmail.com 写道:




ptrdiff pd1 = 34,size_t st1 = 30

(pd1< st1)= 0

(pd1 - st1)= 4

(st1 - pd1)= 4294967292

< / code>


比较pd1不小于st1; pd1应该大于

st1。但是,减号操作的结果是相反的。



ptrdiff_t和size_t是无符号的。 30-34溢出(下溢?)

产生未定义的行为,但是,最常见的实现

会回绕到0xFFFFFFFC,或4294967292.

再次,你不能依赖它,因为超出

积分类型的范围是未定义的。


周三, 2007年1月31日21:37:43 -0800,red floyd< no ***** @ here.dude>

在comp.lang.c ++中写道:

ky****@gmail.com 写道:




ptrdiff pd1 = 34,size_t st1 = 30

(pd1< st1)= 0

(pd1 - st1)= 4

(st1 - pd1)= 4294967292

< / code>


与比较pd1并不少比st1; pd1应该大于

st1。但是,减号操作的结果是相反的。



ptrdiff_t和size_t是无符号的。 30-34溢出(下溢?)

产生未定义的行为,但是,最常见的实现

会回绕到0xFFFFFFFC,或4294967292.



否,ptrdiff_t始终是签名类型。当你执行

两种不同类型之间的算术运算时,在这种情况下

ptrdiff_t是有符号的,而size_t是无符号的,会有

a转换。


如果ptrdiff_t可以保存size_t的所有值,那么

基本上意味着它将比size_t更宽泛,size_t值

将被转换为ptrdiff_t并且该操作将产生一个

签名的ptrdiff_t结果。


因为在此实现中ptrdiff_t是相同或较小的等级

size_t,它是ptrdiff_t,它被转换为无符号的

size_t类型。结果已明确定义。


再次,你不能依赖它,因为超出

整数类型的范围是未定义的。



再次你不正确。对于有符号整数

类型,你所说的是正确的,但对于无符号整数类型则不然。对于无符号类型,没有这样的溢出或下溢的东西。


-

Jack Klein

主页: http://JK-Technology.Com


comp.lang.c的常见问题解答 http:// c- faq.com/

comp.lang.c ++ http://www.parashift.com/c++-faq-lite/

alt.comp.lang.learn.c-c ++
http://www.contrib.andrew.cmu。 edu / ~a ... FAQ-acllc.html


red floyd写道:

ky **** @ gmail.com 写道:


>
ptrdiff pd1 = 34,size_t st1 = 30
(pd1< st1)= 0
(pd1 - st1)= 4
(st1 - pd1)= 4294967292
< / code>

比较pd1不小于st1; pd1应大于
st1。但是,减号操作的结果是相反的。



ptrdiff_t和size_t是无符号的。



否,ptrdiff_t已签名。虽然,在这种情况下,它的值被转换为
到无符号类型。


30-34溢出(下溢?)产生未定义的行为,



无符号整数永不溢出。


但是,最常见的实现

将回绕到0xFFFFFFFC或4294967292.



不仅仅是最常见的实现;在* all * implementation上以这种方式包含无符号算术。


再次,你不能依赖它,因为超出范围

整数类型未定义。



不,你*可以*依赖这种行为,因为标准保证。

-

Clark S. Cox III
cl*******@gmail.com


<code>
#include <iostream>

int main(void)
{
using namespace std;

int p[100];
int* p1 = p;
int* p11 = p + 2;
int* p2 = p + 12;

ptrdiff_t pd1 = (p2 - p1) * size_t(p11 - p) + (p2-p1) - (p11-p1);
size_t st1 = 30;

cout <<"ptrdiff pd1="<<pd1 <<", size_t st1="<<st1 <<endl;
cout <<"(pd1 < st1)="<<(pd1 < st1) <<endl;
cout <<"(pd1 - st1)="<<(pd1 - st1) <<endl;
cout <<"(st1 - pd1)=" <<(st1 - pd1) <<endl;
cout <<endl;

// for (size_t i=0; i < pd1 - st1 ; ++i) cout <<i << endl;

return 0;
}
</code>

àì ?á·?±×·¥à? ???à °á°ú′? ′ùà?°ú °°?à′?′ù.

<code>
ptrdiff pd1=34, size_t st1=30
(pd1 < st1)=0
(pd1 - st1)=4
(st1 - pd1)=4294967292
</code>

With comparison pd1 is not less than st1; pd1 should be greater than
st1. However the result of the minus operation is reversed.

This is not a makeup code but happen to encounter in coding a program.
The C++ Standard Library container has a size() member function
returning size_t, which is an unsigned type, and the subtraction two
between random access iterators returns ptrdiff_t, which is a signed
type. Using such values, some of the for loops went wrong
unexpectedly.

The compiler I used is as following.

<code>
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --enable-languages=c,c+
+,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-
system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-
threads=posix --enable-nls --program-suffix=-4.1 --enable-__cxa_atexit
--enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --with-
tune=i686 --enable-checking=release i486-linux-gnu
Thread model: posix
gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
</code>

Thanks,

Ahn, Ki Yung

解决方案

ky****@gmail.com wrote:

[redacted]
ptrdiff pd1=34, size_t st1=30
(pd1 < st1)=0
(pd1 - st1)=4
(st1 - pd1)=4294967292
</code>

With comparison pd1 is not less than st1; pd1 should be greater than
st1. However the result of the minus operation is reversed.

ptrdiff_t and size_t are unsigned. 30-34 overflows (underflows?)
yielding undefined behavior, however, the most common implementation
would wrap around to 0xFFFFFFFC, or 4294967292.

Again, you cannot rely on that because going outside the range of an
integral type is undefined.


On Wed, 31 Jan 2007 21:37:43 -0800, red floyd <no*****@here.dude>
wrote in comp.lang.c++:

ky****@gmail.com wrote:

[redacted]
ptrdiff pd1=34, size_t st1=30
(pd1 < st1)=0
(pd1 - st1)=4
(st1 - pd1)=4294967292
</code>

With comparison pd1 is not less than st1; pd1 should be greater than
st1. However the result of the minus operation is reversed.

ptrdiff_t and size_t are unsigned. 30-34 overflows (underflows?)
yielding undefined behavior, however, the most common implementation
would wrap around to 0xFFFFFFFC, or 4294967292.

No, ptrdiff_t is and always has been a signed type. When you perform
an arithmetic operation between two different types, in this case
ptrdiff_t which is signed and size_t which is unsigned, there will be
a conversion.

If ptrdiff_t could hold all the values of a size_t, which would
basically mean it would be a wider type than size_t, the size_t value
would be converted to ptrdiff_t and the operation would produce a
signed ptrdiff_t result.

Since on this implementation a ptrdiff_t is the same or of lesser rank
the size_t, it is the ptrdiff_t which is converted to the unsigned
size_t type. The result is well defined.

Again, you cannot rely on that because going outside the range of an
integral type is undefined.

Again you are incorrect. What you say is true for signed integer
types, but not true for unsigned integer types. There is no such
thing as overflow or underflow for unsigned types.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html


red floyd wrote:

ky****@gmail.com wrote:

> [redacted]
ptrdiff pd1=34, size_t st1=30
(pd1 < st1)=0
(pd1 - st1)=4
(st1 - pd1)=4294967292
</code>

With comparison pd1 is not less than st1; pd1 should be greater than
st1. However the result of the minus operation is reversed.

ptrdiff_t and size_t are unsigned.

No, ptrdiff_t is signed. Although, in this case its value gets converted
to an unsigned type.

30-34 overflows (underflows?) yielding undefined behavior,

Unsigned integers never overflow.

however, the most common implementation
would wrap around to 0xFFFFFFFC, or 4294967292.

Not just "the most common implementation"; unsigned arithmetic wraps in
this manner on *all* implementations.

Again, you cannot rely on that because going outside the range of an
integral type is undefined.

No, you *can* rely on this behavior as it is guaranteed by the standard.
--
Clark S. Cox III
cl*******@gmail.com


这篇关于来自ptrdiff_t和size_t的奇怪结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆