C ++内存地址

时间:2019-06-27 12:40:43

标签: c++ memory

如果这是一个重复的问题,请原谅

这是我的代码

#include "stdafx.h"
#include <stdio.h>
#include "iostream"
#include <stdlib.h>
using namespace std;

int main()
{
    char * name = "Hello";

    cout << "2" << endl;
    cout << "Address2 is " << &name <<  "   value at address is " << * (&name) << endl;
    cout << "Next address2 is " << &name + 1 << "   value at address is " << name + 1 << "  " << sizeof(char) << endl;

    cout << "3" << endl;
    cout << "Address3 is " << &name << "   value at address is " << name << endl;

    cout << "Next address3 is " << &name + sizeof name << "   value at address is " << name + sizeof name << endl;
    getchar();
}

这是输出

  1. Address2是003EFAA4,地址为Hello //我很容易理解

  2. 下一个地址2是 003EFAA8(这是我很难理解的地方。我的理解是,考虑到char为1字节,下一个地址应该是003EFAA5吗?

  3. 输出与1相同

  4. 下一个地址2是 003EFAB4(这也是我很难理解的地方。我的理解是,考虑到char指针的大小为4字节,当变量名的地址为003EFAA4时,下一个地址应为003EFAA8? / strong>

我对内存的理解是地址是以字节为单位引用的。如果是这样,那么为什么在上面的数字3中给我的地址再增加4个字节,而在上面的数字4中给我的下一个地址又再增加10个字节?

任何解释将不胜感激。谢谢

4 个答案:

答案 0 :(得分:10)

  

下一个地址2是003EFAA8(这是我很难理解的地方。我的理解是,考虑到char为1字节,下一个地址应该是003EFAA5?

执行&name + 1后,您将转到name类型的下一个地址。 name不是char。它是一个char*,在您的系统上,一个char*的大小为4。这就是为什么它向前移4个字节的原因,因为这是下一个char*所在的位置。

  

下一个地址2是003EFAB4(这也是我也很难理解的地方。我的理解是,考虑到char指针的大小为4字节,当变量名的地址为003EFAA4时,下一个地址应该是003EFAA8。

这基本上与上面发生的事情相同,但是要转到下一个元素char*,而不是转到下一个sizeof name,在本例中,它是第四个元素。

答案 1 :(得分:8)

&name的类型为char**。指针算术的工作方式(如果添加)会增加char*的大小几倍(因为char**指向char*,因此它将指向如果存在char*数组,则下一个char*。在您的系统上,char*的大小看起来是4。因此,如果&name003EFAA4,那么&name + 1003EFAA8(还有4)。

sizeof name4,因此,如果将其添加到&name,它会增加16。因此,乳清会使您得到003EFAB4,比0x1016(或003EFAA4)。

答案 2 :(得分:6)

您这里的间接访问级别太多。

&name是一个字符**,即指向字符指针的指针。这意味着,如果您+1,那么您将添加指针的大小,而不是字符的大小。 name已经是一个字符*。

然后的问题是对名称进行指针算术运算,然后使用cout而不是新char *处的字符串打印指针地址。您可以通过强制转换为void *来实现此目的,例如

cout << "Next address2 is " << (void*)(name + 1)

使用C样式强制转换。

答案 3 :(得分:6)

欢迎使用指针算术。

char *name = "hello";

name是指向字符的指针。它存储"hello"字符串文字的地址,即。字符h的地址(数组的地址等于(等于值)数组的第一个元素的地址)。您应该注意,字符串文字是不可变的,您无法对其进行修改。因此,最好将类型更改为const char*

&name

这是指向变量名的指针。不是指向"hello"字符串文字的指针,而是指向指针的指针。 003EFAA4name变量的地址。变量是由编译器在main()函数内部的堆栈上分配的。

*(&name)

*&规则(在此处)自行排除。因此*&name等于name。这将打印name指针的值,即。这是指向"hello"字符串文字的指针,即。这是指向h字符串文字内的字符"hello"的指针。不是&nameh个字符的地址。

&name + 1

&name具有char **类型,即它作为指向字符的指针的指针。根据指针算法,&name + 1等于(uintptr_t)&name + 1 * sizeof(*&name)的值。 sizeof(*&name)sizeof(name),它是sizeof(char*),所以它是(uintptr_t)&name + sizeof(char*)。在您的体系结构上,sizeof(char*)是4字节(32位系统?),因此指针增加了4。即。 003EFAA4 + 4 = 003EFAA8

name + 1

name的类型为char*。根据指针算术,name + 1等于(uintptr_t)name + sizeof(*name)sizeof(*name)sizeof(char)sizeof(char)被定义为等于1。这将在e字符串文字中打印"hello" char的地址。

&name + sizeof name

&name的类型为char**,因此&name的值递增sizeof(name) * sizeof(char*) times. As sizeof(name)is equal to sizeof(char *){{ 1}} sizeof(char *)* sizeof(char *), this is 4 * 4 = 16`。

ie.

这将指针name + sizeof name 的值增加name的值。 sizoef(name) * sizeof(char)sizeof(name)sizeof(char*)在您的体系结构上,4是1。因此sizeof(char)是{{1}中的字符name + sizeof name的地址}字符串文字,即。 o

@edit重写了一些部分