是否可以使用C?中的宏生成数组的特定排列?
即。如果我有一个带有元素的数组X:
0 1 2 3 4 5
x = ["0","1","1","0","1","0"]
我当时认为可能会有类似这样的宏foo:
#define S_2Permute(x) = [x[5], x[3], x[4], x[2], x[1]]
其中我重新定义了数组的顺序,因此原始位置5中的元素现在处于位置0。
有什么想法吗?
示例使用
我开始创建DES加密算法的实现。 DES需要几个排列/扩展,我必须重新排序数组中的所有元素,有时缩小数组并有时扩展它。我希望能够为我定义一个宏来置换数组。
EDIT2
在DES中,第一步是称为初始置换。所以最初我有一些64位密钥,在这个例子中可以是0-15 hex:
0123456789ABCDEF
扩展为:
0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
IP(初始置换)将置换此字符串,以便数组中的每个元素都处于新位置:
IP =
58 50 42 34 26 18 10 2
60 52 44 36 28 20 12 4
62 54 46 38 30 22 14 6
64 56 48 40 32 24 16 8
57 49 41 33 25 17 9 1
59 51 43 35 27 19 11 3
61 53 45 37 29 21 13 5
63 55 47 39 31 23 15 7
因此,bitstring中的新1st元素将是原始bitstring中的第58个元素(bit)。
所以我将所有这些位存储在一个字符数组中:
x = [0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,1,0,1,0,0,0,1,0,1,0,1,1,0,0,
1,1,1,1,0,0,0,1,0,0,1,1,0,1,0,1,0,1,1,1,1,0,0,1,1,0,1,1,1,1,0,1,1,1,1]
然后只需致电
IP_PERMUTE(x);
宏魔法会将所有位移动到新的正确位置。
答案 0 :(得分:4)
绝对 - 你的榜样几乎就在那里。试试这个:
#define S_2Permute(x) {x[5], x[3], x[4], x[2], x[1]}
然后:
int x[] = {1,2,3,4,5,6};
int y[] = S_2Permute(x); // y is now {6,4,5,3,2}
要记住两件事:
1)在C中,数组从0开始编号,所以你的意思是:
#define S_2Permute(x) {x[4], x[2], x[3], x[1], x[0]}
2)如果您正在使用gcc,则可以使用-E
进行编译以查看预处理器的输出(非常适合调试宏扩展)。
但是,我不认为我实际上是这样做的 - 如果以编程方式生成排列,我会说代码会更容易阅读(并且可能更不容易出错) - 我怀疑它是'这将是一个巨大的性能打击。
既然你说你在编译时遇到了问题,这里有一个适用于gcc 4.6.1的测试程序:
#include <stdio.h>
#define S_2Permute(x) {x[5], x[3], x[4], x[2], x[1]}
int main(void) {
int x[] = {1,2,3,4,5,6};
int y[] = S_2Permute(x);
for(int i = 0; i < 5; i++) {
printf("%d,",y[i]);
}
printf("\n");
}
我使用gcc test.c -std=c99 -Wall
答案 1 :(得分:2)
如果不能提供不同的解决方案,但您是否考虑过使用内联函数而不是宏,那么我是新的如此道歉?
我喜欢单行代码,这些代码与下一个代码的作用相同,但是这样做对我来说更有意义:
//I would have an array that defined how I wanted to swap the positions, I'll assume 5 elements
short reordering[5] = {4,1,3,2,0};
inline void permuteArray(char array[]) {
char swap = array[reordering[0]];
array[reordering[0]] = array[reordinger[1]];
array[reordering[1]] = array[reordinger[2]];
array[reordering[2]] = array[reordinger[3]];
array[reordering[3]] = array[reordinger[4]];
array[reordering[4]] = swap;
}
这可能不像宏那样漂亮或高效,但它可以为您节省一些管理和维护代码的麻烦(并且总是可以换成Timothy建议的宏版本。
答案 2 :(得分:0)
我做的事情有所不同。这是我的代码。进来的变量是ulong,所以然后我将它转换为位数组然后重新排列所有位然后将其转回ulong。
public override ulong Permutation(ulong input, int[] permuation)
{
byte[] test = BitConverter.GetBytes(input);
BitArray test2 = new BitArray(test);
BitArray final = new BitArray(test);
ulong x = 0;
ulong y = 1;
for (int i = 0; i < permuation.Length; i++)
{
final[i] = test2[(permuation[i]-1)];
}
for (int i = 0; i < final.Length; i++)
{
if (final[i] == true)
{
x += (1 * y);
}
else
{
x += (0 * y);
}
y = y * 2;
}
return x;
}