【问题标题】:Trouble understanding pointer cast from struct address to (uint *) [closed]无法理解从结构地址转换为(uint *)的指针[关闭]
【发布时间】:2015-08-19 20:25:27
【问题描述】:

我在向自己解释以下 C 代码时遇到了一些麻烦,似乎没有人能给我一个明确的答案,所以这实际上是我最后的手段。

struct s some_buffer;

uint *RxPtr;

RxPtr = (uint *)&some_buffer;

我知道类型转换是强制RxPtr 指向some_buffer 的唯一方法,因为some_bufferstruct 类型,而RxPtr 只能指向uint。给我带来这么多麻烦的是(uint *) 中的*。我不明白为什么这段代码的作者希望some_buffer 的类型为uint * 而不仅仅是uint

我只发现另外 1 个人问过这类问题。应用于我的问题的答案是&some_buffer 为您提供(struct *),需要将其类型转换为(uint *)

当我这样想时,这是有道理的。但这本质上是在说& = struct *& 不是指针,那么&some_buffer 怎么给我一个(struct *)?就像我之前说的,为什么这段代码的作者希望 some_buffer 的类型为 uint * 而不仅仅是 uint

【问题讨论】:

  • & 是“地址”运算符。应用它会产生一个指向操作数的指针。这在您的“C 语言简介”一书的前几章中有介绍。 RxPtruint*,因为这是周围代码所需要的。
  • XY 问题:序列化结构的正确方法是正确且可移植地序列化其字段。 没有强制转换和警告。
  • 你会感到惊讶,moldbnilo。所有介绍 C 的书籍都说明了指针是什么,以及 & 是什么,但没有详细说明 & 产生指向操作数的指针(如果正确的话)。在过去的几天里,我浏览了大约 5 C 本书。不过感谢您的回答,它确实清除了我的一些想法。

标签: c pointers casting


【解决方案1】:

如果 RxPtr 是一个无符号整数,它就不是一个指针。

之所以有人让一个指向值的指针指向一个结构的地址,通常是为了能够在不关心结构元素的情况下填充结构。

假设 struct some_buffer 类似于:

struct some_buffer
{
 uint header;
 uint first_data;
 uint second_data;
};

并且 rx_data 是一个包含三个 uint 的数组。

然后你可以用以下方式填充 some_buffer 的数据:

some_buffer.head = rx_data[0];
some_buffer.first_data = rx_data[1];
some_buffer.second_data = rx_data[2];

您也可以将一个 uint 指针指向该结构并写入:

ptr = (uint *) &some_buffer;
ptr[0] = rx_data[0];
ptr[1] = rx_data[1];
ptr[2] = rx_data[2];

当你走到这一步时,你甚至可以进一步简化并编写:

ptr = (uint *) &some_buffer;
for(int i = 0; i < 3; i++)
{
   ptr[i] = rx_data[i];
}

由于结构中的每个元素都是 sizeof(uint) 并且指针在指向 uint 时也会增加 sizeof(uint),因此您填充结构的三个元素而实际上不需要知道结构元素的名称.即使您将 header 重命名为 mynewheader,指针代码也将起作用。

如果 RxPtr 是一个无符号整数,你就不能这样做。递增 unsigned int 只会导致 unsigned int 具有不同的值,但不会指向 some_buffer 的不同内容。

【讨论】:

    【解决方案2】:

    some_buffer 是一个东西。 &amp;some_buffer 是那个东西的地址。现在,地址是内存中的一个位置,任何类型都可以存储在一个地址中。在这种情况下,&some_buffer 是结构的地址。

    RxPtr 也被声明为地址,用于存储uint。可能是原作者知道该结构以 uint 开头,并且只是投射指针以反映这一点。但这是不好的做法,可能会误导您。

    【讨论】:

      【解决方案3】:

      我只发现另外 1 个人问过这类问题。应用于我的问题的答案是&amp;some_buffer 为您提供(struct *),需要将其类型转换为(uint *)

      有些日子我想知道是否某些掌握指针的困难是由于 C 使用type * 而不是type &amp; 来表示地址而弄混了水。如果它使用&amp; 代替,那么* 将更自然地与&amp; 相反。

      // wishful thinking
      int x;
      int &addr = &x;
      int y = *addr;
      

      但这不是 C 所做的。当您使用&amp;x 获取变量的地址时,您会得到type *。在第一次学习指针 20 年后的现在,这对我来说似乎很自然,但我记得在我年轻的时候,这种语法看起来非常混乱。

      在我们生活的世界中,C 并不认为&amp;x 是“x 的地址”。相反,它是“指向x 的指针”,因此结果类型是int * 而不是int &amp;

      // reality
      int x;
      int *addr = &x;
      int y = *addr;
      

      变量通常被称为保存指针,而不是地址。请注意,地址仍然正确。说地址并没有错。只是这两个词是同义词,“指针”比较常见。

      (uint &) &some_buffer;   // wishful thinking
      (uint *) &some_buffer;   // reality
      

      这就解释了为什么指针转换写成(uint *)&amp;some_buffer 给你一个“指向some_buffer 的指针”,(uint *) 将该指针转换为另一种类型。

      【讨论】:

      • 谢谢约翰。根据您和 molbdnilo 所说,更清楚的是 & 产生了一个指针。起初我很难相信这一点,因为我认为只有指针才能指向事物。但我猜 & 不是一个指针,它只是在幕后隐含地产生一个?这是正确的说法吗?至于指针周围的混乱,问题在于书籍没有足够详细。我经历过的所有 5 次都说同样的话。 & 给出一个地址,* 是间接运算符,它们是互逆的。细节可能会让初学者感到困惑,但缺乏细节会让我感到困惑!
      • &amp; 给出一个地址,* 是间接运算符,它们是互逆的。这是真的,也是明智的部分。除了作为间接运算符之外,* 还有其他用途,这就是它令人困惑的地方。 * 也用于类型声明和类型转换以表示指针(AKA 地址)类型。这是 not 间接运算符。 int * 中的 **variable 中的 * 不同。前者是类型名,后者是间接运算符。
      猜你喜欢
      • 1970-01-01
      • 2020-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-04
      相关资源
      最近更新 更多