C++ 给指针赋值

C++ 给指针赋值,c++,pointers,dev-c++,C++,Pointers,Dev C++,我在理解指针的概念时有点困难,其中之一是: 让我们声明一个整型变量n,以及指向它的指针*p. int n=23,*p 现在, p=&n,如果我没有错的话,将变量n(比如3000)的地址分配给p。 所以cout假设您通过添加一个cast来编译它 p=(int *)5; 然后取消引用该指针将是未定义的行为。 它可以做任何事情,但你的程序很可能会中止。它可以在不同的系统上表现不同 此外,变量或下一个变量的地址也取决于运行程序的系统。大多数系统对局部变量使用堆栈,但它们可以向上或向下计数,所以您不知道

我在理解指针的概念时有点困难,其中之一是:
让我们声明一个整型变量n,以及指向它的指针*p.
int n=23,*p
现在,
p=&n,如果我没有错的话,将变量n(比如3000)的地址分配给p。

所以
cout假设您通过添加一个cast来编译它

p=(int *)5;
然后取消引用该指针将是未定义的行为。 它可以做任何事情,但你的程序很可能会中止。它可以在不同的系统上表现不同

此外,变量或下一个变量的地址也取决于运行程序的系统。大多数系统对局部变量使用堆栈,但它们可以向上或向下计数,所以您不知道

调试和优化构建也可以发出不同的代码。有些编译器在本地数组或变量后留下空间,因此当您在数组外写入时,它们会给出有意义的错误。但在发布时,它们可能会尽可能地使用内存

为了让事情变得更加不可预测,主流操作系统采用了一种称为地址空间布局随机化(ASLR)的技术

每次程序运行时,变量得到的基址都将随机化。这样,黑客就不能在注入自己代码的地方滥用缓冲区溢出并计算返回地址


所以不,你不能说任何关于变量地址的一般性的东西。您必须检查您的编译器和操作系统。

是的,您是对的&是地址运算符。它给出一个指针,它将指向哪个地址

如果用星号键入p,则表示需要该指针指向的值

Integer从内存中获取4个字节,所以每次创建Integer时,它将从内存堆栈中获取4个字节,可以是降序或升序

您也可以在ide上尝试所有这些

int n = 23,*p;
int n2 = 24;
int n3 = 25;

p = &n;
printf("%d %d %d %d %d",p,n,*p,&n2,&n3);

在您的示例中,这是一个编译器错误

但是我想你想做的是:

int n =23, *p;
p = &n;
//Change the value of p to 3000, p now points to address 3000
p = reinterpret_cast<int*>(3000); 
//Check if the address of n has changed
std::cout << "Address of n : " << reinterpret_cast<int>(&n) << std::endl; 
int n=23,*p;
p=&n;
//将p的值更改为3000,p现在指向地址3000
p=重新解释铸件(3000);
//检查n的地址是否已更改

让我们用一个类比

int  x = 3;
int* x_p = &x;
你可以这样看:你现在有一张纸,叫做
x
,上面写着编号
3
。还有一张纸,上面写着第一张纸的位置。具体如何操作其实并不重要,因此让我们假设第二张纸叫做
x_p
,上面写着
x
。在这方面,

int y = *x_p;
意思是:查看纸张
x\u p
,将其解释为另一张纸张的位置,并获取写在该纸张上的值,即
y
将具有值
3

现在,如果你在纸上写些别的东西会怎么样?首先,如果你仍然试图把它解释为另一张纸的位置,你会失败,或者你会得到一张随机的纸,但不是你要找的那张。第二,这对第一张纸
x
有什么影响?这根本不影响它。指针和其他变量一样都是变量,只是您通常将它们的值解释为其他变量的位置,但指针和指针对象之间没有任何连接


这不是最好的类比,但可能会有所帮助。

您可以将int转换为指针。这是标准的。而标准则保证,如果将指针转换回int,则应获得原始值,前提是其间未发生截断

但取消引用这样的指针是未定义的行为。这意味着,在常见的实现中,如果您试图读取未映射或写地址,则可能会出现段错误或内存冲突,或者由于您读取的位置不知道那里有什么,因此只会得到一个不可预测的值

如果你在那里写,情况会更糟,因为你可能会覆盖程序中的随机位置。想象一下,当你覆盖函数的返回地址时会发生什么

唯一的实际使用情况是,一些特殊的硬件寄存器映射到众所周知的地址。然后你写下:

char *p;
p = 0x60;    // say 0x60 is the address of a special register you want to read
char reg_value = *p;

这不能由标准来定义,因为标准没有对底层平台进行假设,而是一个本地扩展,应该为特定的硬件平台记录。

您不能这样做,
5
不能转换为
int*
。(如果你真的尝试过这个,你可能会自己发现。)很好,很安全,你可以在你的机器上测试。从错误中学习,这是最好的方法。你会得到一个不错的编译器错误。@KerrekSB实际上,他可以手动完成,编写
p=(int*)5如果您知道正确类型的有效地址的值,则可以。如果您使用不同类型的地址,或者只是一个无效的地址,它就是UB。我看了一个关于他们使用现代C++在一个准将上编程Pon的对话,他们在使用内存映射设备时必须这样做。@ NaNaLover也值得提到的是,在64位机器上,正确的地址不一定适合<代码> int <代码>,所以,最好使用
std::ptrdiff\u t
进行这样的实验。变量存储的位置(相对于彼此)由编译器决定,而不是操作系统。@melpomene我的错误,修复。虽然操作系统将决定它将在内存中为程序提供哪些空间来进行自动存储。虚拟和phsyicalIt也取决于内存分配单元;或者内存存储分类器的类型,例如:
全局
堆栈或本地
来自堆
静态
。甚至还有其他的,但这是4个最常见的内存转换单元,它们取决于编译器、操作系统和体系结构
int y = *x_p;
char *p;
p = 0x60;    // say 0x60 is the address of a special register you want to read
char reg_value = *p;