3

我想检查当我增加/减少指针值时指针地址将如何变化。

我的代码是:

void pointers_plus_minus()
{
    char *c = (char *) 0x7fff80ccd35c;
    int *i = (int *) 0x7fff80ccd35c;

    c++;
    i++;

    cout << "char pointer" << c << endl;
    cout << "int pointer" << i << endl;
}

但是这段代码给了我Segmentation fault (core dumped).

我知道地址有问题,但不清楚是什么。如何解决?我正在使用 64 位 Ubuntu。

4

3 回答 3

9

您不能像整数一样对指针进行操作(嗯,不在明确定义的上下文之外)。

只有当指针指向您拥有的数组内时,您c++才可以这样做。i++

糟糕,我认为这实际上是明确定义的,因为 1 个元素被视为 1 的数组,并且您可以在数组末尾多出一个元素。但是,从该指针读取仍然是未定义的。

无论如何,虽然未定义,但崩溃可能是因为cout << c尝试打印出字符串,而不是指针。将其转换为void*

cout << "char pointer" << static_cast<void*>(c) << endl;

虽然这会满足你的好奇心,这很好,但它仍然是未定义的,不应该这样做。

于 2013-05-30T18:31:55.190 回答
5

您询问如何为指针分配常量地址,但这样做 (a) 非常不可移植,并且 (b) 不一定符合您的目的,即查看递增指针的效果。

这是一个程序,可以满足您的好奇心,而不会因未定义的行为而崩溃:

#include <iostream>
int main() {
    const int len = 10;
    char char_array[len];
    int int_array[len];

    char *cp = char_array;
    for (int i = 0; i <= len; i ++) {
        std::cout << "cp = " << static_cast<void*>(cp) << "\n";
        cp ++;
    }

    std::cout << '\n';

    int *ip = int_array;
    for (int i = 0; i <= len; i ++) {
        std::cout << "ip = " << static_cast<void*>(ip) << "\n";
        ip ++;
    }
}

我的(64 位)系统上的输出是:

cp = 0x7fffaa5ddc30
cp = 0x7fffaa5ddc31
cp = 0x7fffaa5ddc32
cp = 0x7fffaa5ddc33
cp = 0x7fffaa5ddc34
cp = 0x7fffaa5ddc35
cp = 0x7fffaa5ddc36
cp = 0x7fffaa5ddc37
cp = 0x7fffaa5ddc38
cp = 0x7fffaa5ddc39
cp = 0x7fffaa5ddc3a

ip = 0x7fffaa5ddc00
ip = 0x7fffaa5ddc04
ip = 0x7fffaa5ddc08
ip = 0x7fffaa5ddc0c
ip = 0x7fffaa5ddc10
ip = 0x7fffaa5ddc14
ip = 0x7fffaa5ddc18
ip = 0x7fffaa5ddc1c
ip = 0x7fffaa5ddc20
ip = 0x7fffaa5ddc24
ip = 0x7fffaa5ddc28

对此的一些说明:

指针增量是有效的,因为每个指针始终指向正确类型的数组的一个元素,或者只是超过它的末尾。(你可以在数组末尾构造一个指针;你不能取消引用这样的指针。)

打印类型指针时产生的输出void*是实现定义的。在我的系统上,它恰好是指针值的十六进制表示,被解释为好像它是一个整数——这可能是它最常见的完成方式。

您可以看到char*指针似乎每次都增加 1,并且int*指针每次增加 4。在我的系统(可能还有您的系统)上,指针存储为字节地址。指针算术以指向类型为单位定义,而不是以字节为单位。递增int*指针会导致它指向上一个位置sizeof (int)之后的内存位置字节 - 在本例中为 4 个字节。所有的指针算法都是这样定义的;ptr2 - ptr1为您提供两个地址之间的元素数量(无论类型ptr1ptr2指向)。

打印的特定值告诉您有关如何在系统上管理内存地址的信息。指针和整数之间的映射一般会反映系统的内存模型。该模型在很大程度上是特定于实现的。

于 2013-05-30T18:39:48.447 回答
-2

段错误,我最喜欢的堆栈溢出旁边的错误消息,是当您尝试写入非法内存空间时。也就是说,当你的程序被加载到内存中时,你怎么能保证你的堆栈/堆空间落在你试图保留的区域内,更何况你为什么要这样做呢?这可能可以在 Assembly 中完成,因为您对硬件的访问权限要低得多,但我严重怀疑它可以在 C 中完成(或者如果可以的话,应该完成)。

于 2013-05-30T18:37:47.873 回答