令我印象深刻的是必须有一个聪明的方法来做到这一点。这不适用于家庭作业,工作或任何事情。我只是用一种有数据交错的文件格式来徘徊。
所以,在通用的C / C ++中,(或其他)给出一些数组
int x[] = ...
有一种巧妙的方法将它分成两个短阵列
short sa1[], sa2[]
使得int数组在中间分割
x[i] = 1111111111111111 1111111111111111
sa1[i] sa2[i]
编辑:对不起,如果没有说得好。对于int数组的每个第i个元素,最左边的16位成为一个数组的第i个元素,最右边的16位成为第二个数组的第i个元素。
所以给出
x[i] = 0001111111111111 1111111100011111
然后
sa1[i] = 0001111111111111
sa2[i] = 1111111100011111
我正在寻找不明显的答案,这些答案不会遍历每个元素,并且会移动并屏蔽每个元素。这很简单:)
答案 0 :(得分:5)
有很多方法可以做到这一点:
假设:
short
是16位。int
是32位。方法1 :(一个简单的循环)
for (int i = 0; i < size; i++){
int tmp = x[i];
sa1[i] = (tmp ) & 0xffff;
sa2[i] = (tmp >> 16) & 0xffff;
}
方法2:SSE2
for (int i = 0; i < size / 8; i++){
__m128i a0 = ((__m128i*)x)[2*i + 0];
__m128i a1 = ((__m128i*)x)[2*i + 1];
a0 = _mm_shufflelo_epi16(a0,216);
a1 = _mm_shufflelo_epi16(a1,216);
a0 = _mm_shufflehi_epi16(a0,216);
a1 = _mm_shufflehi_epi16(a1,216);
a0 = _mm_shuffle_epi32(a0,216);
a1 = _mm_shuffle_epi32(a1,216);
((__m128i*)sa1)[i] = _mm_unpacklo_epi64(a0,a1);
((__m128i*)sa2)[i] = _mm_unpackhi_epi64(a0,a1);
}
如果循环进一步展开,最后一个示例非常快。如果这可以击败所有字节操作库,我不会感到惊讶。
但是,它有以下限制:
前两个可以通过清理代码解决。这很麻烦,但如果你真的想要表现,那可能是值得的。
编辑:
是的,这违反了严格别名,但如果不这样做,几乎不可能使用SSE内在函数。
答案 1 :(得分:3)
int
在您的平台上只有两个short
,您可以reinterpret_cast
将int
数组short
转换为int
数组,然后取偶数/奇数元素。
但是请注意,short
与short
的大小无法保证(int
除int
之外的大小不能超过short
)。例如,short
可能等于int
,或者可能超过2 {{1}} s。即使{{1}}的绝对大小也不能得到保证(典型大小为4和8字节)。
对于真正可移植的解决方案,您可能最好将您要解释的文件的确切格式映射到bit fields。
答案 2 :(得分:0)
你需要知道x的长度,但你可以做类似的事情:
#include <stdio.h>
int main(int argc, char * argv[])
{
int x[] = {1, 2, 3, 4, 5, 6};
int xlen = 6;
short * a = &x[0];
short * b = &x[xlen/2];
printf("%d\n%d\n", a[0], b[0]);
}
a
指向原始int
数组的开头,并允许您以short
增量进行索引。与b
相同,但它从原始int
数组的中间开始。
我会称之为聪明,但是你会收到gcc关于不兼容指针类型的警告。这是我在嵌入式环境中可能会做的事情,但我会确保它在不太受控制的环境中不会引起任何安全问题。