【问题标题】:How to access multiple elements of array in one go?如何一次访问数组的多个元素?
【发布时间】:2014-10-12 21:23:23
【问题描述】:

我有一个数组uint8_t data[256]。但是每个元素都是单字节的。 我的数据总线是 32 位长。所以,如果我想访问 32 位,我会这样做:

DATA = data[i] + (data[i + 1] << 8) + (data[i + 2] << 16) + (data[i + 3] << 24);

但这会在内存中转换为 4 个单独的读取请求,每个请求一个字节。

如何以单笔交易的形式访问全部 4 个字节?

【问题讨论】:

  • 如果 data 的类型为 int [256],则每个求和数不仅读取一个字节。
  • 您必须使用非常非标准的编译器才能使 int data[256]; 由单字节组成。每个“字节”必须至少为 16 位(CHAR_BIT == 16)。我认为你所做的假设有些混乱。如果,正如您的一位 cmets 所建议的那样,您的意思是 uint8_t data[256];,那么一个问题是“您是否要在不是 4 的倍数的 i 值处编制索引”?另一个问题是“如果您尝试将“不正确对齐”的内存地址作为 4 字节单元访问会发生什么?在冒险走捷径之前,您需要知道这两个问题的答案。

标签: c arrays


【解决方案1】:

如果您知道数据的字节顺序(或者您不关心),并且您的数据是对齐的(或者有一个字节寻址过程并且您不关心效率),您可以将数据转换为uint32_t * 并在 4 字节卡盘中访问它,如下所示:

DATA = ((uint32_t *)data)[i/4];

这当然假设 i 是 4 的倍数。

【讨论】:

  • 你应该更准确:如果你知道目标架构是小端的。
【解决方案2】:

只需将data 转换为uint32_t

uint8_t data[256] = {1,2,3,4,5,6,7,8} ;

int main(int argc, char **argv)
{
  int index = 1 ;
  uint32_t d = *(uint32_t *)(data + index) ;
  printf ("%08x\n", d) ;
}

小端架​​构的输出将是

05040302

大端架构的输出将是

02030405

但是,根据运行程序的处理器的架构,您可能会遇到内存对齐问题(如果您处理未对齐的内存,性能会受到影响,或者如果您的处理器不支持未对齐的内存寻址,甚至会崩溃)。

【讨论】:

  • 我试过了,这几乎奏效了:我拥有的数据是 01,02,03,04,05,06,07,08... 当我以 *(long *)(data+0),我得到 0x01030201 而不是 0x04030201。当我访问 *(long *) (data+1) 时,我得到 0x05040302。意思是data[4]=4,但是返回的值是不正确的,你知道为什么会这样吗?
  • 代码在这里运行良好。针对这个特定问题提出关于 stackoverflow 的新问题。
  • 输出会依赖于芯片架构吗?我的印象是输出将与架构无关,就像位移等一样。这可以解释为什么@Rgarg 得到 0x05040302 而不是小端表示,即使他/她可能在芯片上使用 little-引擎盖下的字节序表示。
  • uint32_t d = *(uint32_t *)(data + index) ;index = 1 是未对齐的访问,具有潜在的未定义行为。
  • @chqrlie 在答案的最后一句中已经提到。
【解决方案3】:

也许您应该将数据存储为 32 位数组:

uint32_t data[64];
DATA = data[i];
DATA = data[i+1];
...

【讨论】:

  • 我无法修改数组。它是一个约束。但如果我们从记忆的角度来看,这不就是一回事吗? uint32_t 数据[64] 和 uint8_t 数据[256]?
  • @Rgarg:你的数组是什么类型的?在问题中,您说int data[256];,但在您的评论中,您似乎在说uint8_t data[256];——它们非常不同!事实上,这让你的问题变得一团糟。
【解决方案4】:

正如@dwayne-towell 提到的 - 您需要注意数据的字节顺序。在一个事务中,它可能会像下面的示例那样实现:

#include <stdio.h>
#include <stdint.h>

int
main()
{
        uint8_t data[256];
        uint32_t i, *p;

        // Add some 32bit numbers
        p = (uint32_t *)data;
        for (i = 0; i < sizeof(data)/sizeof(uint32_t); ++i) {
                *(p++) = i;
        }

        // Print some 32bit numbers
        p = (uint32_t *)data;
        for (i = 0; i < sizeof(data)/sizeof(uint32_t); ++i) {
                printf("value=%u\n", *(p++));
        }

        return (0);
}

【讨论】:

    猜你喜欢
    • 2012-04-23
    • 2015-03-16
    • 1970-01-01
    • 1970-01-01
    • 2022-07-15
    • 1970-01-01
    • 2014-06-07
    • 2020-09-06
    • 2013-03-18
    相关资源
    最近更新 更多