【问题标题】:Proper way to access array members as a different type?以不同类型访问数组成员的正确方法?
【发布时间】:2016-05-03 00:29:08
【问题描述】:

我有一大堆uint16_t。

它的大多数成员是uint16_t,但有些是int16_t,有些是uint8_t。

你会怎么处理?


顺便说一下,我试过了:

  1. 指针:

    使用 2 个指针,一个 int16_t* 和另一个 uint8_t*,都初始化为数组的开头,以访问数组的成员 int16_t 和 uint8_t。

    (最初可行,但后来在程序中更改了指针的值时遇到了问题,所以我不相信它。)

  2. 带有联合的类型定义。

    在文件.h中:

    typedef union {
      uint16_t  u16[NO_OF_WORDS];     // As uint16_t
      int16_t   s16[NO_OF_WORDS];     // As int16_t
      uint8_t   u8[2 * NO_OF_WORDS];  // As uint8_t
    } ram_params_t;
    extern ram_params_t ram_params[];
    

    在文件.c 中:

    ram_params_t ram_params[] = {0};
    

    (真的被炸了。)

  3. 铸造。

    (我并没有走得太远。)

【问题讨论】:

  • 如何知道哪些元素属于哪些类型?你能给我们展示一下选角的尝试吗?如果它们真的必须是单个数组,这似乎是最明智的方法。
  • 你为什么要这样做?为什么不只拥有几个其他类型的变量?这似乎很容易出错,并且无法维护?
  • > 你为什么要这样做? -- 因为阵列(在嵌入式系统中)是与外界共享的。外部系统可以访问该阵列并且只能访问该阵列。数据种类繁多。
  • > 你怎么知道哪些元素属于哪些类型? -- 按索引。我知道索引 3 处的成员是 int16_t,索引 5 处的成员是一对字节。

标签: c arrays casting unions


【解决方案1】:

您的尝试 #2 的问题在于您创建了一个数组数组。

要么这样做:

typedef union {
  uint16_t  u16;     // As uint16_t
  int16_t   s16;     // As int16_t
  uint8_t   u8[2];   // As uint8_t
} ram_params_t;
extern ram_params_t ram_params[NO_OF_WORDS];

ram_params_t ram_params[NO_OF_WORDS];

uval16  = ram_params[i].u16;
sval16  = ram_params[i].s16;
uval8_1 = ram_params[i].u8[0];
uval8_2 = ram_params[i].u8[1];

或者你这样做:

typedef union {
  uint16_t  u16[NO_OF_WORDS];     // As uint16_t
  int16_t   s16[NO_OF_WORDS];     // As int16_t
  uint8_t   u8[2 * NO_OF_WORDS];  // As uint8_t
} ram_params_t;
extern ram_params_t ram_params;

ram_params_t ram_params;

uval16  = ram_params.u16[i];
sval16  = ram_params.s16[i];
uval8_1 = ram_params.u8[2*i];
uval8_2 = ram_params.u8[2*i+1];

我也认为您的尝试 #1 没有任何问题。我认为我可能会这样做而不是使用联合。

【讨论】:

  • > 我认为您的尝试#1 没有任何问题——直到今天我也没有发现,当其中一个指针中的值发生更改时,会破坏数组中的数据。指针在启动时设置一次。我如何确定它在运行一年后仍能正确设置而无需重置?这只是不可靠。我想我必须定期检查它的价值。
  • 你的指针被破坏表明你的程序中的其他东西是错误的并且正在破坏内存。我实际上建议您重试 #1 并调试您的程序,否则您可能最终会遇到另一个神秘的失败。
  • > 你的指针被损坏表明你的程序中的其他东西是错误的并且正在破坏内存。 - 是的,一点没错!我找到并修复了它。但这是对依赖指针的危险的警钟。
  • “我们应该小心地从经验中摆脱出来,只有其中的智慧并停在那里,以免我们像坐在热炉盖上的猫一样。她永远不会坐在又是一个热炉盖,这很好,但她再也不会坐在冷的炉子上了。” - 马克吐温
  • @Davide Andrea:很有趣。我使用的编译器不会那样做。我想你必须解决编译器的奇怪行为。
【解决方案2】:

其他类型的数组元素必须与uint16_t 大小相同,所以只需转换它们即可。在 8 位数据的情况下,高 8 位可能是未定义的,所以我将它们屏蔽掉了。

#include <stdio.h>

#define uint16_t    unsigned short
#define int16_t     short
#define uint8_t     unsigned char

int main() {
    uint16_t n;

    // convert uint16_t to int16_t
    n = 0xFFFF;
    printf ("%d\n", (int16_t)n);

    // convert uint16_t to uint8_t
    n = 168;
    printf ("%c\n", (uint8_t)(n & 0xFF));

    return 0;
}

程序输出是

-1
¿

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-18
    • 1970-01-01
    • 2014-01-25
    • 2021-04-24
    • 1970-01-01
    • 2015-04-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多