【问题标题】:what does *p contain?*p 包含什么?
【发布时间】:2016-11-26 15:45:06
【问题描述】:

根据多个来源,指针p 在取消引用时指向一个值。因此,我们可以说一个指针包含一个地址作为它的值,当使用解引用运算符 (*) 时,返回 地址处的值

指针可以被赋值如下:

int a = 90; int *p = &a;

如果我们分配一个指针,它的值如下:

int *p; *p = 60;

60 分配给p 并在取消引用时导致未定义的行为,因为 60 不是有效地址。 (根据the answer to this question)。

但是,对于以下代码:

    int a = 90;
    int *p = &a;

    printf ("p is %d \n",*p);
    printf ("a is %d \n", a);
    printf ("address is %p \n",p);

    *p = 100;

    printf ("p is %d \n",*p);
    printf ("a is %d \n", a);   
    printf ("address is %p \n",p);

收到以下输出:

p 是 90
a 是 90
地址是 0028FED8

p 是 100
a 是 100 地址是 0028FED8

即,表达式*p = 100 更改a 的值,而不是p 包含的值。

如何 ??????

【问题讨论】:

  • *p = &a 完全错误,任何体面的编译器都会拒绝。
  • 打印地址使用%p,而不是%d
  • 是的,它被拒绝了。我在这个问题上打错字了。

标签: c pointers dereference


【解决方案1】:

*p = &a 甚至无法编译。 p 是一个指向 int 的指针。它当前具有未定义的值,因此将任何内容分配给 *p 都是未定义的行为,并且很可能会崩溃。然而,即使 p 确实 指向一个 int,您也只能将一个 int 分配给 *p,&a 是一个指向 int 的指针,而不是一个 int,所以这不会编译。

在第二个示例中,*p = 60,p 的值未定义,因此您尝试将 60 存储到内存中未定义的位置。瞬间崩溃。 p 没有被这个修改,所以你的解释是错误的。 p 未设置为 60。您不能将 p 设置为 int。您只能将其设置为指向 int 的指针。

正确:

p = &a; 
*p = 60;

【讨论】:

    【解决方案2】:

    你一开始写的代码:

    int *p;
    int a = 90;
    *p = &a;
    

    无效,第 1 行中的星号 (*) 表示它是一个指针,它不是第 3 行中的解引用运算符。

    以下代码:

    int a = 90;
    int *p = &a;
    

    相当于:

    int a = 90;
    int *p;
    p = &a;
    

    (p) 是一个指针,现在指向(a)的地址

    *p = 100;
    

    所以,您只需为 a, a = 100 分配一个值。 并且您正在从相同的地址打印相同的值。

    【讨论】:

      【解决方案3】:

      你问过:

      即,表达式 *p = 100 改变了 a 的值,而不是 p 包含的值。

      您可以阅读注释部分以了解每行 C 代码的解释,我没有使用确切的地址位置,而是使用任意地址来进行演示:

      int *p;       // Stack variable pointer to integer type w/ p's address being 4 bytes      @  0x00000000
      int a = 90;   // Stack integer variable `a` and initializing it to the value of 90 located @  0x00000040 
      *p = &a;      // Dereferencing the pointer `p` to be equal to the address of `a` ... One would think
                    // that the address value of `a` 0x00000040 in hex would be stored into `a` which
                    // has the value of 64 in decimal, however this is not always the case and this should be 
                    // undefined behavior, but can still compile and run depending on the compiler and architecture. 
                    // It may run or crash or not even compile or build at all. Most compilers should throw an error.
      
      *p = 100;    // 'p' is located at 0x00000000 and contains the value 0x00000040 and by dereferencing it
                   // it will assign the value of 100 to the stack address location of 0x00000040. Thus this
                   // changes the value of `a` to 100
      
                   // These two statements are in a sense equivalent  
      *p = 100;    a = 100;
                   // If one was to assign the address of `a` to `p` as such:
       p = &a;
      

      编辑

                  // Therefor the statement `*p=100` will only work if the statement
                  // `p=&a` is defined and evaluated beforehand.
      

      编辑 现在关于基于标题的问题:"what does *p contain?" 提供的操作的原始代码 *p 实际上包含垃圾或在声明时分配给它的内容。

      【讨论】:

      • > 十六进制的a的地址值将被存储到a
      • @simrandhamija 非常正确,但那行代码是未定义的行为;我最初确实声明地址值将存储为十六进制,但它的十进制等效值为 64,因为变量类型是 int。但事实并非如此。
      • 你不是说“a 的十六进制地址值会被存储到p”吗?
      • @simrandhamija 是的,如果语句有效,这在逻辑上会发生这种情况,但对于一些新手来说,他们可能认为它将实际值存储为十进制转换,但事实并非如此。
      • @simrandhamija 从评论部分获取句子并省略最后一部分 with the value of 64 which is decimal, ... 并且只阅读句子的第一部分。 One would think that the address value of 'a' (0x0...) which is in hex would be stored into 'a'... 与您在第一次和最初的评论中回复我的内容相同。
      【解决方案4】:

      根据多个来源,指针p 在取消引用时指向一个值。

      不完全是。一个指针指向一个对象。取消引用指针会生成该对象。在需要值的上下文中使用对象会产生存储的值。

      int *p = &a;
      

      p 现在指向的对象是a

      *p = 100;
      

      取消引用p 会生成指向对象,即a。由于这不是需要存储值的上下文,因此不会读取 a 的值,它仍然是分配了值 100 的对象 a

      或者,简单地说,*p 表示a,因此*p = 100 表示a = 100

      【讨论】:

      • 如果我错了,请纠正我,但 C 不是过程语言吗? C 中没有对象,因为它不是 OOP 语言。
      • @simrandhamija 不,我的术语确实是正确的,但我可以理解它令人困惑。 C 所称的对象与 OOP 中的不同。 C 所称的对象只是一块内存,通常是一个变量,或者由诸如malloc 之类的函数的结果所指向的东西。
      猜你喜欢
      • 2014-10-16
      • 2012-01-13
      • 2012-11-25
      • 2011-08-18
      • 2019-11-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多