C语言字符指针算术运算

4

我正在学习指针算术,然后遇到了这样的内容:

char *str1, *str2;

/* stuff in between */

int f = str2 - str1;
< p >“str2-str1”返回什么?假设< code> str1="foo" 和< code> str2="foobar" 。

3个回答

14

根据你所提出的问题,结果未定义。要让指针差运算正确工作,它们必须来自同一数组序列(动态、自动甚至是自动 VLA 都没有区别),或者一个在最后一个元素之后的地址:

§6.5.6 加法运算符 (第9段)

当从两个指针中减去时,它们都必须指向同一数组对象的元素或者数组对象的最后一个元素之后的位置;其结果是两个数组元素下标之间的差值。这个结果的大小是实现定义的,其类型(带符号整数类型)在头文件<stddef.h>中定义为ptrdiff_t。如果结果不能用该类型的对象表示,则行为未定义。换句话说,如果表达式PQ分别指向数组对象的第i和第j个元素,则表达式(P)-(Q)的值为i-j,前提是该值适合于ptrdiff_t类型的对象。此外,如果表达式P指向数组对象的一个元素或者最后一个元素之后的一个元素,并且表达式Q指向相同数组对象的最后一个元素,则表达式((Q)+1)-(P)的值与((Q)-(P))+1-((P)-((Q)+1))的值相同,并且如果表达式P指向数组对象的最后一个元素之后的一个元素,则该表达式的值为零,即使表达式(Q)+1并不指向数组对象的任何元素。106

也就是说,如果你想符合上述规则来重新表述问题,可以这样说:

#include <stdio.h>
int main()
{
    const char *p = "Hello World";
    const char *q = p+7;
    printf("%td\n", q-p);
    return 0;
}

输出

7

原因在标准的引用部分有解释。


3

编辑

这个问题的答案取决于具体情况。

1)在您的情况下,由于指针没有指向任何东西,结果将是垃圾。

2)如果两个指针指向程序空间中的两个有效内存位置,则结果将是这两个位置之间的内存字节数。虽然这没有任何意义,并且根据C规范是未定义行为,如果两个指针没有指向同一个数组或字符串。如果两个指针指向同一个数组或字符串,则结果将是同一数组中两个元素之间的元素数量(当指针指向该数组中那两个元素时)。查看 SO 问题以获取示例和更多解释。


1
如果两个指针都指向同一个“对象”,那么我会说仅适用于第二种情况。 - alk
“结果将是这两个位置之间的内存字节数”,这是一个常见的结果,但不被C规范定义 - 这是未定义行为。其他可能的结果包括程序故障或f中的无意义值。 - chux - Reinstate Monica

0

f = str2 中的内存地址 - str1 中的内存地址。 "foo""foobar" 是这些指针所指向的内存位置的值。

示例:

如果 str2 = 0x8000000a

并且 str1 = 0x80000000

str2 - str1 = 0x8000000a - 0x80000000 
str2 - str1 = 0x0a 

1
我认为只有当两个指针指向完全相同的“对象”时,这才成立。 - alk
ab是本地变量。 - Ishmeet
此外,你的措辞不准确,因为"str2的内存地址"应该是&str2,而str2 - str1实际上是指指针变量str2中存储的地址。 - alk
是的,谢谢@alk,我确实是指存储在指针变量str2str1中的地址。 - Ishmeet
1
C语言并没有规定地址在堆栈上,因此我的上面的答案将具有不同和非连续的内存位置。甚至C语言也没有规定“堆栈”。这个结果取决于平台/编译器,因为它是未定义的行为。 - chux - Reinstate Monica
显示剩余3条评论

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