为什么我不能添加指针?

17

我有非常类似这样的代码:

LINT_rep::Iterator::difference_type LINT_rep::Iterator::operator+(const Iterator& right)const
{
    return (this + &right);//IN THIS PLACE I'M GETTING AN ERROR
}

LINT_rep::Iterator::difference_type LINT_rep::Iterator::operator-(const Iterator& right)const
{//substracts one iterator from another
    return (this - &right);//HERE EVERYTHING IS FINE
}

err msg: Error  1   error C2110: '+' : cannot add two pointers

为什么我只在一个地方遇到错误,而不是两个地方都有?


指针的加法意味着什么?如果你的家庭地址是3472 Main,添加一个数字2将会给你3474 Main,很可能是邻居。但是将这两个地址相加得到的是6946。这是什么意思? - Lee Daniel Crocker
7个回答

61

742 翠柏路 + 1 = 743 翠柏路

742 翠柏路 - 1 = 741 翠柏路

743 翠柏路 - 741 翠柏路 = 2

743 翠柏路 + 741 翠柏路 = ???


2
@Indrek,你认为第四行的结果应该是什么?将两个地址相加根本没有意义。 - fredoverflow
1
:) 很好的答案。真的,我是认真的。 - SigTerm
2
@Fred:1484 Evergreen Terrace。当然啦。;-)(我同意@SigTerm的观点:好的例子) - James McNellis
度数提供了更清晰的解释,但是“度数”既可以表示绝对温度,又可以表示温度差,所以大多数人不理解它们是不同的单位。例如85度 + 5度差=90度100度 - 5度差=95度 100度 - 95度 = 5度差 100度 + 50度 = ? - Jeremy Salwen
1
@Jeremy 我认为“常青露台”比“度数”更合适,因为单位不会产生任何混淆。“常青露台”与单位没有任何关系,它只是一个指示从哪里开始计数的指针,类似于数组的开头。 - fredoverflow

43

C++中不允许指针相加,只能进行指针相减。

这是因为对两个指针进行相减可以得到一个可解释的结果——它们在内存中的偏移量。类似地,你可以将整数加、减到指针上,这意味着“向上或向下移动指针”。但是,将一个指针加到另一个指针上是很难解释的。这样操作的结果代表什么?

如果你确实需要一个指向内存中某个地址的指针,而这个地址是另外两个地址之和,你可以将这两个指针转换为 int 类型,相加后再将其转化回指针类型。但请记住,这种解决方案需要非常小心地处理指针算术,而且你真的不应该这样做。


7
将数据类型强制转换为整型并不是一个好主意,因为整型的大小(sizeof(int))可能与指针大小(sizeof(void*))不同。使用像 ptr_diff_t 这样的类型会是更好的选择。 - Mike Weller
1
如果你要尝试这个,我建议使用[u]intptr_t。在我的编译器/运行时/操作系统组合中,sizeof(ptrdiff_t) != sizeof(void *) - Logan Capaldo
再次证明我的名字。添加两个指针是我经常做的事情 - 特别是在处理低级别的东西时,现在我应该总是将指针转换为'size_t'。 - AnArrayOfFunctions
@FISOCPP:“将两个指针相加是我经常做的事情”,但这并不意味着你应该经常这样做。它有什么目的?它没有逻辑结果。 - chbaker0
1
我确实有理由这么说,但你真的认为我现在还记得吗?不过我猜想这一切都与相对地址有关 - 你需要添加一个基地址来正确地使用它们。在 Windows 进程中,这些被称为“RVA”。 - AnArrayOfFunctions
显示剩余3条评论

4
两个指针相减可以得到它们之间的距离。那么两个指针相加的结果会是什么?

15
@KMKY,如果你能计算(date2 - date1)并得出时间间隔,那么你是否也能计算(date2 + date1)?它会得出什么结果? - Marcelo Cantos
1
@cHao,感谢你终于加入了真正的讨论。我的问题的目的是帮助原帖作者自己发现问题,而不让他们感到愚蠢。通过自己的推理过程来学习比被灌输答案要更加深入和持久。顺便问一下,什么才算是对指针的“严重”缺乏知识,与普通的缺乏知识有何区别? - Marcelo Cantos
1
@cHao,假设一个人通过VBA首次学习编程,然后决定尝试C或C++。他们阅读一本书,并在跟随书中代码的过程中编写代码。在指针章节,他们发现可以减去指针但不能加上它们。意识到大脑中有些东西没有理解,他们决定在程序员论坛上提出问题。您会建议这样的人不要费心学习C或C++吗,因为这超出了他们的能力范围?请不要混淆“不理解”和“无法理解”。我们都天生对指针的整个概念缺乏严重的知识。 - Marcelo Cantos
1
@cHao,你可能已经在这个领域呆了太久。我教过很多人基础编程(不是BASIC),指针对初学者来说并不容易理解。 - Marcelo Cantos
1
好的,@cHao,我放弃了。你真是个天才,指针对你来说就像母猪尿尿一样轻松(借用莫扎特的话),而任何第一次就不明白的人都是个白痴,根本不值得费心去尝试。 - Marcelo Cantos
显示剩余16条评论

2

其他回答已经解释了为什么你所做的不起作用,但我猜测你想为迭代器定义典型的 operator+,但在尝试中迷失了方向。

指针和标准随机访问迭代器都允许将指针或迭代器按整数值向前移动。对于迭代器,定义了一个 operator+,它接受一个整数值作为参数并返回一个迭代器。

LINT_rep::Iterator LINT_rep::Iterator::operator+(int distance) const;

您可以将此类运算符定义为方法,但这种方法将允许您编写。
iterator + distance

但不是

distance + iterator

为使加法满足交换律,您需要定义一个友元非成员函数,第一个参数为距离,第二个参数为迭代器对象。
friend LINT_rep::Iterator LINT_rep::Iterator::operator+(int distance, const  LINT_rep::Iterator & rhs);

2
我猜想在您的示例中,您期望的结果是将指针移动到一个偏移量而不是另一个指针。
在C++中,您可以减去2个指针(获取它们之间的内存偏移量),或者将一个指针加上一个整数值(将指针移动到另一个内存位置,该位置增加value * sizeof(object_class))。仅将2个指针相加在C++中没有意义,但是如果您确信要将2个内存位置地址相加,只需将它们作为无符号整数值相加(使用类型转换)。

除了在64位编译器中,其中sizeof(x*)> sizeof(int)。关于指针大小与任何其他类型的大小相关的大小没有保证。 - cHao

0
为什么我在一个地方出现错误而在另一个地方没有?
即使您被允许添加两个指针,这样做也是不正确的:
 return (this + &right);

指向空处。想一下 - this 可能是类似于0x00123456的东西,而&right将在相同的范围内(例如0x00000000..0x80000000 - 例如0x00321321)。如果将它们加起来,结果地址将非常远离两个变量(0x00123456 + 0x00321321 == 0x00444777,这将远离“this”和&right),您可能会进入保留内存(win上的0x8xxxxxxx等)。此外,指针可能会溢出。这(可能)就是为什么被禁止的原因。

如果要将某些内容添加到指针,请添加整数。


0
假设你有两个指针并且你知道其中一个或者都可能是null。你想要返回那个不是null的指针,如果两个都是null则返回 null。最简单的方法是对它们进行求和/XOR操作。这是对指针求和的正确做法。

1
标准并不保证空指针是全零位。 - Lee Daniel Crocker
“空指针常量是一个整数类型的积极值(5.19),其评估为零或std::nullptr_t类型的prvalue。”只要您在一个所有位为零的值为0的整数类型的机器上工作,它就成立。 - Šimon Hrabec

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接