C++ C/C++;:指针算法

C++ C/C++;:指针算法,c++,c,pointers,math,pointer-arithmetic,C++,C,Pointers,Math,Pointer Arithmetic,我读了一点指针算术,发现两件事我不懂,也不知道它的用途 address_expression - address_expression 而且 address_expression > address_expression 请有人向我解释一下,它们是如何工作的,何时使用的 编辑: 我想说的是,如果我只取两个地址并减去它们,它们会产生什么 如果我拿两个地址进行比较,结果是什么 编辑: 我现在理解了地址减法的结果,但是比较地址我还是不明白 我知道1第一个表达式从一个指针减去另一个指针。作为一

我读了一点指针算术,发现两件事我不懂,也不知道它的用途

address_expression - address_expression
而且

address_expression > address_expression
请有人向我解释一下,它们是如何工作的,何时使用的

编辑:


我想说的是,如果我只取两个地址并减去它们,它们会产生什么

如果我拿两个地址进行比较,结果是什么

编辑: 我现在理解了地址减法的结果,但是比较地址我还是不明白


我知道1第一个表达式从一个指针减去另一个指针。作为一个简单的例子,这可能是有用的,考虑一个C字符串。字符串位于连续内存中,因此,如果您有字符串的第一个字符的地址和最后一个字符的地址,则可以通过执行以下操作来查找字符串的长度:

int strLength = (last_char_address - first_char_address) + 1;
这种指针算法是类型感知的,这意味着算法的结果表示两个指针之间特定类型的元素数。在上面使用
char
的示例中,差异是字符数。这同样适用于两个
结构的指针


类似地,第二个表达式只是比较指针,结果将是1或0。作为一个非常简单的示例,数组元素5的地址始终是
元素4:
&string[4]>&string[5]
的地址为true。

减去两个指针地址返回该类型的元素数


因此,如果有一个整数数组和两个指针,减去这些指针将返回整数值之间的数值,而不是字节数。与char类型相同。因此,您需要注意这一点,特别是当您使用字节缓冲区或宽字符时,您的表达式计算的值是正确的。如果需要基于字节的缓冲区偏移量来存储不使用单个字节的内容(int、short等),则需要首先将指针转换为char*。

指针通常被视为表示内存地址的数字,如0x0A31FCF20(十进制为2736770848)或0xCAFEDEAD(有时系统会用它来表示错误,我不记得细节了。)

指针比较通常用于对指针数组进行排序。当您需要检查指针是否在指针列表中时,排序后的指针数组非常有用;如果列表已排序,则不必查看列表中的每个元素以确定指针是否在该列表中。您需要使用比较对列表进行排序

当您拥有指向数据块的指针,并且需要访问不在数据块开头的内容时,通常会使用指针算法。例如:

const char *string = "hello world!"
const char *substring = string+6;
std::cout << string << "\n";
std::cout << substring << std::endl;
这里我们得到了“hello world!”或
“world!”
的前6个字符后的字符串。请记住,如果可能的话,应该在可用的地方使用
std::string
。与指针算法非常类似的概念是随机访问迭代器

减去指针可以帮助您找到这两个指针之间的距离。如果您有一个指向数组第一个元素的指针,并且有一个指向超过数组最后一个元素的一个元素的指针,减去这两个指针可以帮助您找到数组的大小


另一种可能将指针视为整数的情况是在一个优化版本的链表中,称为XOR链表。您可以找到有关它的更多详细信息。如果您愿意,我可以对此进行扩展;请在注释中告诉我。

指针减法生成相同类型的两个指针之间的数组元素数

比如说,

int buf[10] = /* initializer here */;

&buf[10] - &buf[0];  // yields 10, the difference is 10 elements
指针比较。例如,对于
关系运算符:
操作产生
1
,如果左侧的指向数组元素或结构成员位于右侧的指向数组元素或结构成员之后,则产生
0
。记住数组和结构s是有序序列

 &buf[10] > &buf[0];  // 1, &buf[10] element is after &buf[0] element

在许多方面,你可以把一个地址当作
int
。唯一的区别是
int
表示该地址中大小的数量。例如,如果
int*p
碰巧有值,比如说,
234
(来自一些安全的指令,例如
p=new int[12];
),它代表地址234。如果我们做
p+=1;
,它只是增加了int的大小。现在
p
是(假设这个例子是4字节int)238,也就是
p[1]
。事实上
p[x]
相当于
*(p+x)
。您可以像int一样比较和。在某些上下文中,这很有用,例如在给定的示例中
p[0]
现在指的是
p[1]
。这避免了像
p=&p[1]这样的操作
不必要地取消引用。

这里有几个答案说明指针是数字。这不是C标准规定的指针的准确描述

在很大程度上,您可以将指针视为数字和内存中的地址,前提是(a)您了解指针减法将字节之间的差异转换为元素(被减法的指针的类型),以及(b)您了解此模型打破的限制

以下使用了1999 C标准(ISO/IEC 9899,第二版,1999-12-01)。我希望以下内容比询问者要求的更详细,但是,鉴于此处的一些错误陈述,我认为应提供准确的信息

根据6.5.6第9段,您可以减去指向同一数组元素的两个指针或指向数组最后一个元素的指针。因此,如果您有
inta[8],b[4];
,您可以从指向a[2]的指针中减去指向a[5]的指针,因为a[5]和a[2]是数组中的元素
 &buf[10] > &buf[0];  // 1, &buf[10] element is after &buf[0] element