带有宏的C数组排列

时间:2012-02-09 02:44:12

标签: c macros

是否可以使用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);

宏魔法会将所有位移动到新的正确位置。

3 个答案:

答案 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;
        }