【问题标题】:Type cast address in C在 C 中键入转换地址
【发布时间】:2013-08-30 09:43:56
【问题描述】:
typedef struct iomFixedPIA 
{
    UINT16      state;  /* State    */
    UINT16      modStatus;/* Module status*/
} IOM_FIXED_PIA;

#define IOM_PIA_SIZE 256 /* Size of PIA per IO module */

typedef char CM_IOM_PIA [IOM_PIA_SIZE]; /* PIA for one module */

printf("Actual PIA address from PIA offset = %x  modid: %d and pPIA: %x \n",
       CI856_CM_ADRS(CI856_PIA_OFFSET), pParMsg->modId,
       ((CI856_CM_ADRS(CI856_PIA_OFFSET)) + pParMsg->modId) );

pMod->pPIA = (IOM_FIXED_PIA *)
             ((CM_IOM_PIA *) (CI856_CM_ADRS(CI856_PIA_OFFSET)) + pParMsg->modId);
// question here ^^

printf(" pMod PIA= %x  \n", pMod->pPIA);

如果我运行上面的代码,我会得到如下输出。

Actual PIA addres from PIA offset = 300051c modid: 1 and pPIA: 300051d
pMod PIA= 300061c and POA= 3007020

我的问题是。

  1. 当我们在上面输入 caste to type (CM_IOM_PIA *) 时,为什么我们看到的值是 300061c 而不是 300051d?
  2. 为什么我们在类型转换 (CM_IOM_PIA *) 之后再对 (IOM_FIXED_PIA *) 进行类型转换,地址没有变化?
  3. 一般来说,如果我们进行类型转换,地址是否会发生变化?

【问题讨论】:

  • 这个说法正确吗:typedef char CM_IOM_PIA [IOM_PIA_SIZE];。我的意思是可以 onetypedef char 输入数组类型吗?
  • @nishant:是的。这将CM_IOM_PIA 定义为长度为IOM_PIA_SIZEchar 数组的同义词。
  • 您可能想了解指针算法。

标签: c casting structure


【解决方案1】:

事实上,类型转换不会改变变量的地址,它会改变计算机解释变量的方式。地址不会改变,因为您的变量可以是 8 位、32 位或 64 位,它总是从同一个地址开始。但是,如果您有一个数组并将其转换为不同的类型,则当您对其进行交互时,您的程序将迭代最小的大小,例如:

char*    array;
int*     i;

array = malloc(sizeof(char) * 4);
i = (int*)array;

您将拥有 4 * 8 位,因此您将拥有 32 位,可以将其转换为 int,但是如果您在 int 数组上进行迭代,您将耗尽内存,因为程序将通过 sizeof(int) 所以你会超出你的内存分配。

希望对你有所帮助。

【讨论】:

    【解决方案2】:

    这是由于

    中缺少大括号
    (CI856_CM_ADRS(CI856_PIA_OFFSET)) + pParMsg->modId);
    

    添加后的类型转换。

    【讨论】:

      【解决方案3】:
      typedef char CM_IOM_PIA [IOM_PIA_SIZE];
      

      是一个指向 256 字节的 char 的指针 在 C 中,当您向指针添加 1 时,指针数据的大小会增加。如果是 32 位整数数据指针+1 指向下一个整数,那么指针提前 4 个字节。在您的特定情况下,结构大小为 256 字节,每次添加 1 时指针移动 256 字节。

      (CM_IOM_PIA *) is a 256 char pointer so (CM_IOM_PIA *) +1 point to your address + 256 => 300061c 
      

      这只是在加法之前进行转换的运算符优先级问题,因此它增长了 256 而不是 1。如果在 (CI856_CM_ADRS(CI856_PIA_OFFSET)) + pParMsg->modId 周围添加括号以在转换之前进行数学运算,则简单的解决方法。

      【讨论】:

      • 你能详细说明一下吗?我没有得到这个
      【解决方案4】:
      char *foo = NULL;
      int *bar = NULL;
      printf("%p %p\n", foo+1, bar+1);
      

      将输出 1 和 4(很可能,假设 sizeof(int) == 4)。使用原始类型的 sizeof 解决数学问题。

      【讨论】:

      • 你的答案和 Hulor 的都应该合并。
      【解决方案5】:

      要在两个printf()s 中获得相同的地址,而不是这样做:

      pMod->pPIA = (IOM_FIXED_PIA *)
               ((CM_IOM_PIA *) (CI856_CM_ADRS(CI856_PIA_OFFSET)) + pParMsg->modId);
      

      做:

      pMod->pPIA = (IOM_FIXED_PIA *)
               ((CM_IOM_PIA *) ((CI856_CM_ADRS(CI856_PIA_OFFSET)) + pParMsg->modId));
      

      在第二个printf()

      因此添加 + pParMsg->modId 将基于 (CI856_CM_ADRS(CI856_PIA_OFFSET)) 的类型完成,与基于 CM_IOM_PIA 类型完成的 OP 相对。

      【讨论】:

        猜你喜欢
        • 2013-04-11
        • 2011-05-31
        • 1970-01-01
        • 1970-01-01
        • 2021-06-20
        • 1970-01-01
        • 2010-10-02
        • 2016-07-26
        • 1970-01-01
        相关资源
        最近更新 更多