C指针声明之间的区别

Difference between C pointer declarations

这些声明有什么区别?

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

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

正确。

第一部分 (int *ptr_2) 创建一个指向 int.

的指针

第二部分(&val)returns变量的地址val.

int *ptr = val;

会将 val 分配给 ptr2

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

中几乎没有意义。

另请注意,如果您不对其进行初始化,val 将包含一个随机值(实际上是 RAM 中的那个点)。

why is the first method wrong?

我不确定你想做什么,但第一种方法可能是 没有按照你的期望去做

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

int * ptr = (int *)val;

这样做就是告诉编译器您知道自己在做什么,并且希望编译器的行为与 "first method" 的行为相同。

正如用户 "pmg" 在他的评论中所写,如果您直接访问硬件(例如在微控制器编程或开发操作系统时),"first method" 可能会有用。

What is the difference of these declarations?

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

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 表示:"A pointer to the variable val".

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

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

val 然而意思是:"The value of the variable val".

如果我们使用的是32位的Windows或Linux操作系统,我们已经将变量hello的地址写入变量val中标记为 "line 1".

的行

val 的值被复制到标记为 "first method (1)" 的行中的 ptr2,因此 ptr2 包含指向 hello不是指向val的指针。

当然 val 的值很重要:

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

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

您尝试执行的操作在两种情况下均有效,但在第一种情况下您没有正确使用该功能。

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

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

另一方面,

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

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

int val = some_integer;
int *ptr = val;

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

An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.56)