34

我很难理解*(uint32_t*)

假设我有:

uint32_t* ptr;
uint32_t num
*(uint32_t*)(ptr + num); // What does this do? Does it 
4

4 回答 4

63

uint32_t是保证 32 位的数字类型。该值是无符号的,这意味着值的范围从 0 到 2 32 - 1。

这个

uint32_t* ptr;

声明了一个类型为 的指针uint32_t*,但该指针未初始化,也就是说,该指针没有特别指向任何地方。尝试通过该指针访问内存将导致未定义的行为,并且您的程序可能会崩溃。

这个

uint32_t num;

只是一个类型的变量uint32_t

这个

*(uint32_t*)(ptr + num);

ptr + num给你一个新的指针。它被称为指针算术。这就像常规算术一样,只是编译器会考虑类型的大小。可以将ptr + num其视为基于原始ptr指针的内存地址加上对象的字节数num uint32_t

(uint32_t*) x是一个演员表。这告诉编译器它应该将表达式x视为uint32_t*. 在这种情况下,甚至不需要它,因为ptr + num已经是uint32_t*.

*开头是解引用运算符,用于通过指针访问内存。整个表达式等价于

ptr[num];

现在,因为这些变量都没有被初始化,所以结果将是垃圾。

但是,如果您像这样初始化它们:

uint32_t arr[] = { 1, 3, 5, 7, 9 };
uint32_t *ptr = arr;
uint32_t num = 2;

printf("%u\n", *(ptr + num));

这将打印 5,因为ptr[2]是 5。

于 2018-02-16T20:07:16.833 回答
13

uint32_t中定义stdint.h,因此可能需要包含它

#include <stdint.h>

此标头应定义uint32_t为正好采用 32 位的无符号整数类型

于 2018-11-06T18:08:18.430 回答
3

这并没有真正做任何事情。让我给你一个不同的例子:

uint32_t data;
void *pointer = &data;
*(uint32_t *)pointer = 5;

首先,void*表示“通用”指针。它可以指向任何类型的对象。

现在,(uint32_t *)意思是“解释pointer为指向具有 type 的对象的指针uint32_t

表达式的其余部分仅表示“在此指针存储的位置存储 5”。

如果你想知道它是什么uint32_t,那是一个正好是 32 位的无符号整数。和pointer + num的地址相同pointer[5]

于 2018-02-16T20:09:35.537 回答
0

这种类型的表达式通常用于类型双关语。如果您不熟悉类型双关语,主要思想是绕过类型系统,以便您可以将某些内容视为与实际不同的类型(即,将 int a 视为 double)

类型双关语背后的主要思想是您获取一个指向当前变量的指针,然后通过将其转换为该类型的指针然后取消引用它来将其转换为不同的类型,因此您所指的常用转换和取消引用 ( *(uint32_t *)=转换为无符号 32 位 int 指针,然后取消引用)。

正如其他人指出的那样,您的代码“什么都不做”,因为您将一个 int 转换为一个 int,这没有任何效果。但是,如果你想将一个 int 变成一个 double ......

uint32_t num=5;
double& myvar=*(double*) &num;

现在您可以将nums 内存作为双通孔操作,myvar即使num它仍然是一个 Int。这是一个糟糕的想法,只是作为使用双关语的玩具示例。

于 2021-02-22T11:57:03.770 回答