【问题标题】:How does the int *ptr= 5; is different than that of int *ptr= address of variable?int *ptr= 5;与 int *ptr= 变量地址不同?
【发布时间】:2020-03-19 07:11:16
【问题描述】:

虽然它非常基本并且可能看起来很傻,但我试图了解 int *ptr = 450xc8750; (一些数字)int *ptr= &a; (变量地址).

我已经知道的是:

  • 指针用于存储变量地址和修改指向变量的内容(但我想知道它是如何实现的)
  • 在后一种情况下,我可以将*ptr 分配给合法的不同地址。
  • 但是,在第一种情况下它是非法的!。

如果地址/数字都是整数,为什么后者是非法的? 存储在内存中时它们的处理方式有何不同?

我有两段代码/程序基本上可以突出显示相同的内容:

案例 1:

#include <stdio.h>

int main()
{    
    int *ptr = 0xc42; // is this stored in read only memory?!! which later leads to seg faults in further assignments?!
    *ptr = 45; //illegal leads seg fault.
    return 0;
}

案例 2:

int main()
{
    int a=10, b=20;
    int *ptr = &a;  // is here get any special treatment and object will be created for *ptr!!!
    *ptr = &b; //legal
    printf(" *ptr = %d \n", *ptr);
    *ptr = 20; //legal !!
    printf(" *ptr = %d \n", *ptr);
    *ptr = 50; //legal
    printf(" *ptr = %d \n", *ptr);
    return 0;
}

正如我们所见,*ptr = 20*ptr = 50 是合法且没问题的! (没有分段错误)。

为什么int *ptr = 0xc989 或 5 的赋值与 int *ptr = &amp;variable 不同?

【问题讨论】:

  • 使用int *ptr = ....,您声明了一个指向整数的指针,并使用非真实地址对其进行初始化。等于 0xc42 的是 ptr,而不是 *ptr!稍后您访问该地址,这是非法的,因为该地址是非法的。
  • @RobertoCaboni 感谢您的回复。那么,是否 int *ptr = &a 在案例 2 中创建对象,并且稍后可以更改为不同的整数值,如案例 2?但是如果缺少 case-1?我的理解是对的吗!!?案例1分配如何导致非法是我试图理解的,如果我错了,请纠正我。

标签: c pointers


【解决方案1】:

让我们从基础开始:指针是一个变量,其中包含指向给定类型数据的地址。如果我们声明

datatype* foo;

foo(当前未初始化)将包含datatype 类型变量的地址,并将其推迟

*foo = ...;

我们正在访问该地址并将其值存储在那里。


在这两种情况下我们都有* foo,但它们不一样!

  • 在第一种情况下,星号指的是datatype。变量类型为datatype *;变量名是foofoo 包含一个地址。
  • 在第二种情况下,我们取消引用地址,以便访问它。星号引用变量以执行指针取消引用。

所以,当你写的时候

int *ptr = 0xc42; // is this stored in read only memory?!!
                  // which later leads to seg faults in further assignments?!
*ptr = 45; //illegal leads seg fault.
  • 使用int *ptr = 0xc42;,您对编译器说您正在声明一个名为ptr 的变量,其类型为int *,其第一个值为0xC42注意:正如用户 Lundin 正确指出的那样,此分配需要进一步转换才能成为有效的 C)
  • 使用*ptr = 45;,您正在访问ptr 指向的地址并分配值45。合法吗?好吧,如果您之前分配了一个有效地址(一般来说,如果您使用&amp; 运算符为指针分配另一个变量的地址,例如int *ptr = &amp;a;)。但是如果你给它分配一个随机整数......它可能会导致分段错误。

【讨论】:

    【解决方案2】:

    从逻辑上讲,如果您确定位置 0xc989 保留了您需要的内容,int *ptr = 0xc989 完全有效(关于您的思维概念,正如 Roberto Caboni 所说)。

    从技术上讲,正如 Lundin 所说,您需要根据 C 标准对其进行转换。

    【讨论】:

    • 感谢您的回复,我基本上很想知道,尽管我们假设 0xc989 具有有效的内容 will 进行下一次分配 *ptr = 45;合法化?如果不是 case-1 和 case-2 有什么区别呢?
    • @B_San 如果不是只读的,你可以读/写。
    • @B_san 查看我的评论。
    • 它不是完全有效的,它是无效的 C.stackoverflow.com/questions/52186834/…
    • @Lundin 是正确的,但不是OP错误的真正核心。他们认为使用int *ptr= 42; 他们只是为了那个连续的*ptr 推迟指针。
    【解决方案3】:

    首先,int *ptr = 0xc42; 不是有效的 C,并且不会在配置为严格标准 C 的编译器上干净地编译。对于 gcc、clang 和 icc,这意味着使用 -std=c11 -pedantic-errors 进行编译。详情请见"Pointer from integer/integer from pointer without a cast" issues

    int *ptr = (int*)0xc42; 是有效的 C 但有问题。为了澄清,这在指针变量本身中存储了一个地址,它不存储一个值。所以如果你知道在内存地址0xc42有一个int大小的项,比如内存映射的硬件寄存器,那么你可以直接点做。但是这样做时,只有使用volatile:volatile int *ptr = (volatile int*)0xc42; 才有意义。这样的代码在嵌入式系统和其他与硬件相关的编程中很有意义。

    至于为什么您的第二个示例工作正常,那里的地址是由链接器而不是程序员分配的,因此它们将指向有效的分配数据。

    【讨论】:

      猜你喜欢
      • 2022-01-15
      • 1970-01-01
      • 2013-03-13
      • 2018-08-29
      • 2020-08-03
      • 1970-01-01
      • 2020-09-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多