【问题标题】:Difference between C pointer declarationsC指针声明之间的区别
【发布时间】:2020-06-07 08:14:57
【问题描述】:

这些声明有什么区别?

以下哪一项是正确的,为什么该方法是正确的?

int val;
int *ptr = val; // first method
int *ptr_2 = &val; // second method

【问题讨论】:

  • int *ptr = val; 需要您的编译器进行诊断。如果您的编译器没有报错,我建议您停止使用该编译器并选择更好的编译器。
  • 编译器发送一个转换错误@pmg
  • 啊!好漂亮的编译器 :) 始终注意编译器诊断!
  • 如果您在嵌入式系统上,在独立环境中,在裸机上工作,...,(您碰巧知道可以使用int 来存储地址) 你可以正确安全地使用第一个选项和演员:int address = 0xDEADBEEF /* bare metal */; int *ptr = (int*)address;

标签: c pointers variable-assignment


【解决方案1】:
int *ptr_2 = &val;

是正确的。

第一部分 (int *ptr_2) 创建一个指向 int 的指针。

第二部分(&val)返回变量val的地址。

int *ptr = val;

会将val分配给ptr2

从技术上讲,第一个可能有效(编译器可能会显示警告或转换错误,请参阅 cmets)。如果地址以整数形式存储在 val 中,则可以这样使用该地址,但将地址存储在 int 中几乎没有意义。

还要注意val 将包含一个随机值(实际上是 RAM 中的那个点),如果你不初始化它。

【讨论】:

  • @NisanAbeywickrama,因为我已经编辑了我的问题:int *ptr = val; 会将 val 的值分配给 ptr2。
  • 从技术上讲,第一个是不正确的——不管指针是否适合int
  • @NisanAbeywickrama:您正在尝试使用 int 类型的值初始化 int * 类型的对象。这些类型不兼容,因此编译器需要发出诊断。如果您将val 的值转换int *,例如:int *ptr = (int *) val;,那么这将抑制诊断,但您的代码可能无法按预期运行。
  • @dan1st -- int *ptr = val; 不是“有点正确”,它只是不正确。这是一个违反约束,需要编译器诊断(可能是警告或错误,标准不关心哪个)。
【解决方案2】:

您尝试做的事情在这两种情况下都有效,但在第一种情况下您没有正确使用该功能。

int val;
int *ptr_2 = &val; // second method

这是正确的,它会起作用。

另一方面,

int val;
int *ptr = val; // first method

不起作用。您尝试做的事情是这样的:

int val = some_integer;
int *ptr = val;

在这种情况下,如果some_integer 可能是某个有效的端口号;通过使用ptr 变量,您将能够访问端口以写入/读取它。最正确的做法是您将 ptr 声明为 volatile 以实现此目的。但是,指针的这种使用是实现定义的,它不能从一个编译器移植到另一个编译器或从一个系统移植到另一个系统——它对于嵌入式系统和使用特定编译器很有用。将 int 转换为指针的确切定义是这样的:

整数可以转换为任何指针类型。除先前规定外, 结果是实现定义的,可能没有正确对齐,可能不指向 引用类型的实体,并且可能是一个陷阱表示。56)

【讨论】:

    【解决方案3】:

    为什么第一种方法不对?

    我不确定你想做什么,但第一种方法可能没有达到你的预期

    因此,除非你像这样编写第一个方法,否则编译器会给你一个警告信息:

    int * ptr = (int *)val;
    

    这样做你告诉编译器你知道你在做什么,并且你希望编译器按照“第一种方法”的行为行事。

    正如用户“pmg”在他的评论中所写,如果您直接访问硬件,例如在微控制器编程或开发操作系统时,“第一种方法”可能会很有用。

    这些声明有什么区别?

    让我们把程序稍微复杂一点,看看发生了什么:

    int val;
    int hello;
    int world;
    int *ptr1;
    int *ptr2;
    int *ptr3;
    int *ptr4;
    int *ptr5;
    int *ptr6;
    
    val = (int)&hello; // line "1"
    ptr1 = &val; // second method
    ptr2 = val;  // first method (1)
    
    val = (int)&world; // line "2"
    ptr3 = &val; // second method
    ptr4 = val;  // first method (2)
    
    val = 0;
    ptr5 = &val; // second method
    ptr6 = val;  // first method (2)
    

    =”运算符将右侧的值复制到左侧的变量中。

    &val 表示:“指向变量val 的指针”。

    因此指向变量val的指针将被复制到变量ptr1ptr3ptr5中,这三个指针变量将指向变量val

    在这种情况下,变量val 的值无关紧要。

    val 然而意味着:“变量val”。

    如果我们使用的是 32 位 Windows 或 Linux 操作系统,我们已将变量hello 的地址写入变量val 中标记为“第 1 行”的行中。

    val 的值被复制到标记为“第一种方法 (1)”的行中的ptr2,因此ptr2 包含指向hello 的指针,而不是 指针到val

    当然val 的价值确实很重要:

    变量ptr4 将包含一个指向变量world 的指针,变量ptr6 将具有值NULL

    使用 64 位 Windows 或 Linux 操作系统,ptr2ptr4 甚至可能在上面的示例中具有无效值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-19
      • 2010-12-16
      • 1970-01-01
      • 1970-01-01
      • 2020-04-20
      • 2022-01-16
      相关资源
      最近更新 更多