在C ++中,为什么字符串的地址尽管是十六进制格式,但是不能存储在long int变量中?

时间:2017-11-26 11:52:52

标签: c++ arrays pointers

我有以下代码:

#include <iostream>
using namespace std;

int main(){
    string texts[] = {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"};
    return 0;
}

代码:

cout << &texts[0] << endl;

给出输出:

0x7ffc7869f3c0

但是,

long int address = &texts[0];

给出编译时错误:

In function ‘int main()’:
5.cpp:9:29: error: invalid conversion from ‘std::__cxx11::string* {aka std::__cxx11::basic_string<char>*}’ to ‘long int’ [-fpermissive]
  long int address = &texts[0];

为什么我收到此错误?

1 个答案:

答案 0 :(得分:0)

地址是地址,而不是数字。对地址的算术运算通常没有意义(并且指针运算有细微差别),例如,将两个地址相乘是没有意义的。

您可以使用uintptr_tintptr_t。它是一些可以在地址中传送的整体类型。所以你可以编码

 uintptr_t ia = (uintptr_t)(&texts[0]);

但你通常不应该。在我的Linux x86-64上,uintptr_t相当于64位unsigned long

请记住,地址是处理器和操作系统以及编译器,因此系统特定。有时它们在相同程序的“相同”执行之间有所不同(阅读ASLR)。顺便说一下,在某些处理器上,地址比单个数字更复杂(例如在20世纪80年代x86的16位模式下)。

因此,如果您关心portable C ++代码(通常应该如此),则无需将地址转换为整数类型。

另一方面,如果您正在编写特定于处理器和操作系统的内容(例如,newmalloc低于系统调用的实现),您将关心关于地址内的各种位,所以你要投射它(以不可移植的方式)。如果您正在编写某些virtual memory内核的operating system子系统,您甚至会更关心地址中的位等...

您的cout << &texts[0]会生成一些特定于实现的输出,这些输出最适合用于调试目的(但对其他内容并不多)。 C ++ 11标准足够模糊,允许任何其他输出(我的感觉是任何地址的pinkroses输出都符合标准的字母,但我可能是错的)。因此,如果你关心可移植性,你不应该依赖它(或者地址看起来像任何具体的“数字”)。

更糟糕的是相反的演员阵容,从uintptr_t到一些指针。它们是可能的,但通常仅在某些特定的系统上。它们仅在某些特定案例中有意义。大多数数字都不会产生明智的指针(例如,因为你的virtual address space永远不会是满的或密集的)所以你不应该非常谨慎地投射它们。

一个相关的概念是关于undefined behavior。有很多有趣的事情需要阅读和说明。