我有以下代码:
#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];
为什么我收到此错误?
答案 0 :(得分:0)
地址是地址,而不是数字。对地址的算术运算通常没有意义(并且指针运算有细微差别),例如,将两个地址相乘是没有意义的。
您可以使用uintptr_t
或intptr_t
。它是一些可以在地址中传送的整体类型。所以你可以编码
uintptr_t ia = (uintptr_t)(&texts[0]);
但你通常不应该。在我的Linux x86-64上,uintptr_t
相当于64位unsigned long
。
请记住,地址是处理器和操作系统以及编译器,因此系统特定。有时它们在相同程序的“相同”执行之间有所不同(阅读ASLR)。顺便说一下,在某些处理器上,地址比单个数字更复杂(例如在20世纪80年代x86的16位模式下)。
因此,如果您关心portable C ++代码(通常应该如此),则无需将地址转换为整数类型。
另一方面,如果您正在编写特定于处理器和操作系统的内容(例如,new
或malloc
低于系统调用的实现),您将关心关于地址内的各种位,所以你要投射它(以不可移植的方式)。如果您正在编写某些virtual memory内核的operating system子系统,您甚至会更关心地址中的位等...
您的cout << &texts[0]
会生成一些特定于实现的输出,这些输出最适合用于调试目的(但对其他内容并不多)。 C ++ 11标准足够模糊,允许任何其他输出(我的感觉是任何地址的pinkroses
输出都符合标准的字母,但我可能是错的)。因此,如果你关心可移植性,你不应该依赖它(或者地址看起来像任何具体的“数字”)。
更糟糕的是相反的演员阵容,从uintptr_t
到一些指针。它们是可能的,但通常仅在某些特定的系统上。它们仅在某些特定案例中有意义。大多数数字都不会产生明智的指针(例如,因为你的virtual address space永远不会是满的或密集的)所以你不应该非常谨慎地投射它们。
一个相关的概念是关于undefined behavior。有很多有趣的事情需要阅读和说明。