如何在C++中为指针分配常量地址?

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;
}

但是这段代码给我返回了分段错误(核心已转储)

我知道地址出了问题,但是不清楚具体是什么问题。如何修复呢?我正在使用64位Ubuntu系统。


4
cout << "char pointer" << c << endl;c 解释为指向以零结尾的字符数组的第一个元素的指针。使用 cout << "char pointer" << static_cast<void*>(c) << endl; 来打印地址。 - Daniel Fischer
3个回答

9

你不能像操作整数一样操作指针(除非在明确定义的上下文中)。

只有当指针指向你拥有的数组内部时,才允许进行c++i++操作。

哎呀,我觉得这实际上是被定义了的,因为1个元素被视为一个1大小的数组,而且你可以超过数组的末尾一个元素。不过从那个指针读取仍然是未定义的。

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

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

虽然这可以满足您的好奇心,但它仍然是未定义的,不应该这样做。


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指向的任何类型)。

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


-2

除了堆栈溢出之外,段错误是我最喜欢的错误消息,当您尝试写入非法内存空间时会发生。话虽如此,当您的程序已加载到内存中时,如何保证堆栈/堆空间落在您要保留的区域内,更重要的是为什么要这样做?这可能是汇编语言可以完成的事情,因为您可以更低级地访问硬件,但我严重怀疑它是否可以在C语言中完成(如果可以的话也不应该这样做)。


解释我的反对票:什么?我不明白这个回答如何解决问题,甚至它本身也没有意义。 - Nik Bougalis

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