使用C将u64数组重新解释为u16的3D而不改变内存分配

我非常难过,我有一个指向无符号64位整数数组的指针.每个64位整数实际上代表16位整数,因此它应该被分成16位数组,例如:

36348941应吐出:

0,0,554,41997

但是在C中我看不到执行此类型转换的方法.我理解C在内存管理方面有很大的潜力,我希望我不必遍历数据来执行此操作,而只需更改数据在内存中的解释方式,让处理器分配和为我的程序取消分配内存将耗费时间(它需要尽可能快地运行 – 最好少于20毫秒).

如果我简单地说:

arg1 = *(unsigned short (*))(&arg2);

我发现数据截断了这些位,因此每64位整数只吐出一个值,上面的情况就是41997.

这只是应用程序的另一个棘手问题的第一部分,接下来需要将这个16位值数组转换为三维数组,而我可以通过执行以下操作来编译该程序:

const int I = 4;
const int J = 256;
const int K = 256;
arg1 = *(unsigned short (*)[I][J][K])(&arg2);

但是这给了我没有数据,我已经看到这个工作在其他语言,但他们重新分配内存,因此耗时,最好我希望所有这一切发生在处理器,不需要内存分配,因为它只需要内存中位的映射是不同的,而不是数据本身.

然后,我需要能够将此数据作为指向三维数组的指针传回.这样做的原因是我正在努力实现这一目的的语言就像上面提到的那样,内存分配但是调用C DLL的开销很小,所以似乎有可能成为一个解决方案.

我也研究了联盟,但我现在明白这是一种使用联盟的错误方式.

多年来我没有碰过C,所以任何帮助都会非常感激.

最佳答案 首先,你不能使用uint16_t *或类似的东西来做这件事.这是因为严格的别名规则:它只允许通过某种类型的表达式访问内存,如果内存最初是通过该类型编写的(带有一个简短的例外列表).

如果你确实想要这样做,你还必须依赖编译器扩展来编译类似C语言但没有严格的别名规则,例如: gcc用开关-fno-strict-aliasing.

更便携的方式是使用联合:

union U
{
    uint64_t a[10][10];
    uint16_t b[10][40];
};

工会取代了严格的别名规则;你可以将数据写入a并从b中读出.

当然,输出的顺序将根据平台而不同.

点赞