【问题标题】:Trying to understand * and & in C++ [duplicate]试图理解 C++ 中的 * 和 & [重复]
【发布时间】:2015-12-25 22:19:04
【问题描述】:

我有几个问题。这不是家庭作业。我只是想更好地理解。

如果我有

int * b = &k;

  1. 那么k 必须是整数,而b 是指向k 在内存中的位置的指针,对吗?

  2. b 的底层“数据类型”是什么?当我输出它时,它会返回像0x22fe4c 这样的东西,我假设它是内存位置2293324 的十六进制,对吗?

  3. 内存位置“2293324”到底在哪里? “堆”?如何输出值,例如,内存位置012 等?

  4. 如果我输出*b,这和直接输出k是一样的,因为*在某种程度上意味着b指向的值。但这似乎与b 的声明不同,后者被声明为int * b = k,所以如果* 表示“值”,那么并不意味着“将b 声明为k 的值?我知道它没有,但我仍然想确切地理解这在语言方面意味着什么。

  5. 如果我输出&b,这实际上是返回指针本身的地址,与k无关,对吧?

  6. 我也可以执行int & a = k;,这似乎与执行int a = k; 相同。这种方式一般不用&吗?

【问题讨论】:

  • @intboolstring 这不是重复的,因为我的一些问题没有在那个链接中解决。
  • 嗯,你应该把那些没有解决的放在那里。
  • 另外,根据该链接中的 cmets,某些信息是不准确的。我不想学习不准确的东西。
  • @SeanHill:“我的一些问题没有在那个链接中解决”那么你应该问一个单一的、具体的问题,而不是随机列出的问题。

标签: c++ pointers memory


【解决方案1】:

1- 是的。

2- 没有“基础数据类型”。它是一个指向 int 的指针。这就是它的本质。它与 c/c++ 的“int”或“char”数据类型一样。

3- 你甚至不应该尝试输出不是你分配的内存值。那是分段错误。你可以尝试做 b-- (这使得“b”在实际位置之前指向“int”。至少,你的程序认为它是一个 int。)

4- * 带指针是一个运算符。对于任何数据类型,它都是另一种数据类型。这就像 = 符号。当你放 == 时它有一个含义,当你放 = 时它有另一个含义。该符号不一定与它的含义相关。

5- &b 是 b 的方向。它与k有关,而b指向k。例如,如果您执行 (**(&b)),则您正在使 b 的方向指向的值指向的值。这是k。当然,如果你没有改变它。

6-int & a = k表示将a的方向设置为k的方向。 a 无论如何都会是 k。如果您执行 a=1,则 k 将为 1。它们都是对同一事物的引用。

当然可以进行更正。我是这么理解的。

【讨论】:

  • (**(&b)) 和 *b 一样吗?在这种情况下我该如何解释**?
  • 是的,它们是一样的。 ** 意味着两个 * 运算符。也就是说,他们需要一个“指向指针的指针”才能工作。它们返回传递给它们的值所指向的值所指向的值。有点乱,但你可以理解为*(*(&b))
  • 它可以无限深吗? *******&b?
  • 试试看,如果你这样做的话,你的编译器会做什么。
  • @SeanHill 如果您的意思是int****** b;,那取决于编译器,但请阅读c2.com/cgi/wiki?ThreeStarProgrammer。此外,您刚刚写的内容会导致错误,因为 **&b 是 k 的值,所以添加另一个 * 将尝试取消引用 kint)。即使它以某种方式成功,它也会使您的程序崩溃,因为您尝试访问可能受保护的内存位置。
【解决方案2】:

回答您的问题:

  1. 是的,bpointerk:它包含k在堆中的地址,但不包含k本身的值。

  2. b的“数据类型”是int:本质上,这告诉我们b指向的地址是int的地址,但这无关b 本身:b 只是变量的地址。

  3. 不要尝试手动将内存分配到特定地址:内存是根据初始化后对象的大小分配的,因此内存地址是间隔开的,以便为在内存,因此手动更改这是一个坏主意。

  4. * 在这种情况下是对b 的取消引用。正如我所说,b 是一个内存地址,但*bat b 的地址。在这种情况下,它是k,因此操作*b 与操作k 相同。

  5. 正确,&b 是指针的地址,与kb 本身不同。

  6. 使用int & a = k 会创建一个对k引用,它可以像k 本身一样使用。这种情况很简单,但是,对于需要更改位于函数本身范围之外的变量的值的函数,引用是理想的。

例如:

void addThree(int& a) {
   a += 3;
}

int main() {
    int a = 3; //'a' has a value of 3
    addThree(a); //adds three to 'a'
    a += 2; //'a' now has a value of 8

    return 0;
}

在上面的例子中,addThree 引用了a,这意味着main() 中的int a 的值是由函数直接操作的。

这也适用于指针:

void addThree(int* a) { //Takes a pointer to an integer
   *a += 3; //Adds 3 to the int found at the pointer's address
}

int main() {
    int a = 3; //'a' has a value of 3
    addThree(&a); //Passes the address of 'a' to the addThree function
    a += 2; //'a' now has a value of 8

    return 0;
}

不是带有复制构造的参数:

void addThree(int a) {
   a += 3; //A new variable 'a' now a has value of 6.
}

int main() {
    int a = 3; //'a' has a value of 3
    addThree(a); //'a' still has a value of 3: The function won't change it
    a += 2; //a now has a value of 5

    return 0;
}

【讨论】:

    【解决方案3】:

    彼此之间有赞美之词。 * 要么声明一个指针,要么取消引用它。 & 要么声明(左值)引用,要么获取对象或内置类型的地址。因此,在许多情况下,它们协同工作。要创建一个对象的指针,您需要它的地址。要将指针用作值,请取消引用它。

    【讨论】:

      【解决方案4】:

      3 - 如果 k 是一个局部变量,它在堆栈上。如果 k 是静态变量,则它位于程序的数据部分中。这同样适用于任何变量,包括 b。如果使用 new, malloc(), calloc(), ... ,则指针将指向堆中的某个位置。如果使用 alloca()(或 _alloca()),则指针将指向堆栈(alloca() 类似于使用局部可变长度数组)。

      涉及数组的示例:

      int array_of_5_integers[5];
      int *ptr_to_int;
      int (*ptr_to_array_of_5_integers)[5];
      
          ptr_to_int = array_of_5_integers;
          ptr_to_array_of_5_integers = &array_of_5_integers;
      

      【讨论】:

        猜你喜欢
        • 2019-03-04
        • 2022-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-10
        • 2018-01-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多