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

使用C将u64数组重新解释为u16的3D数组,而不更改内存分配,c,arrays,memory,memory-management,C,Arrays,Memory,Memory Management,我非常困惑,我有一个指向无符号64位整数数组的指针。每个64位整数实际上代表16位整数,因此应将其拆分为16位数组,例如: 36348941应表示为: 0,055441997 然而,在C语言中,我看不到执行这种类型转换的方法。我理解C在内存管理方面有很大的潜力,我希望我不必为了执行此操作而遍历数据,而只是简单地更改数据在内存中的解释方式,让处理器分配和取消分配内存对我的程序来说会很耗时(它需要尽可能快地运行-最好小于20毫秒) 如果我简单地说: arg1 = *(unsigned short (

我非常困惑,我有一个指向无符号64位整数数组的指针。每个64位整数实际上代表16位整数,因此应将其拆分为16位数组,例如:

36348941应表示为:

0,055441997

然而,在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\u t*
或类似的东西来实现这一点。这是因为严格的别名规则:如果内存最初是通过某个类型的表达式编写的,那么它只允许通过该类型的表达式访问内存(有一个简短的例外列表)

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

更便于携带的方式是使用工会:

union U
{
    uint64_t a[10][10];
    uint16_t b[10][40];
};
联合会取代严格的别名规则;您可以将数据写入
a
并从
b
读取


当然,输出的顺序会因平台而异。

如何定义
arg2
呢?感谢您的关注,arg2在函数原型中被定义为无符号长*arg2。请注意,在许多32位平台上,long的长度只有4字节。此外,索引I、J、K的顺序可能与您的in不一致tention-如果你有一个64位整数序列,你不能通过3D数组的第一个索引对4个16位“平面”进行索引,而是通过最后一个索引。最后,小端性和大端性都有问题,取决于你运行代码的平台,字节的顺序会不同,给出不同的(有时不正确)结果.Hag内存
arg2
指向堆上已分配的位置?如果
arg2
是指针,那么显然涉及
&arg2
的任何内容都是错误的…如果“源”数据不存在,则显示
arg2
的声明以及如何为其分配指向的空间(以及如何将数据放入该空间),这将有助于显示
arg2
的声明(此处为64位数组)已使用
malloc()在堆上分配
或者朋友们,它保证与任何边界正确对齐,不是吗?是的,但严格的别名规则与对齐注意事项完全不同。我认为可以安全地假设
uint64\u t
uint16\u t
正确对齐。是的,你是对的。我自己刚刚明白了这一点……谢谢提醒方法!;-)