C可以在编译时排序吗?

时间:2015-03-25 23:53:19

标签: c sorting compile-time

是否可以在编译时在C?

中对元素进行排序

语法是次要的,我在考虑像这样的宏:

SORT(9, -1, 12, 4)   // expands to: -1, 4, 9, 12
SORT(dog, cat, cow)  // expands to: cat, cow, dog

但是我不会对任何API皱眉,只要它排序而不发出单个CPU指令。

要求非常宽松:

  • 纯C,无C ++ 。保持在C标准之内会很好,但已建立的语言扩展是公平的游戏。
  • 编译器是唯一允许的工具。 Unix sort或自制的代码生成器不受欢迎,因为它们使构建步骤复杂化。
  • 任何元素类型都可以。它可以排序,例如数字但不是字符串。
  • 固定长度的API很好。必须调用SORT_5来排序5个元素才行。

我意识到解决方案可能会使用一些几乎没有编译的语言巫术,我只是想知道它是否可能。

3 个答案:

答案 0 :(得分:7)

这是一种宏观方法:

#define GET_1_of_3(a, b, c) ((a) < (b) ? ((c) < (a) ? (c) : (a)) : ((c) < (b) ? (c) : (b)))
#define GET_2_of_3(a, b, c) ((c) > (a) && (c) < (b) || (c) < (a) && (c) > (b) ? (c) : ((b) > (a) && (b) < (c) || (b) < (a) && (b) > (c) ? (b) : (a)))
#define GET_3_of_3(a, b, c) ((a) > (b) ? ((c) > (a) ? (c) : (a)) : ((c) > (b) ? (c) : (b)))
#define SORT_3(a, b, c) GET_1_of_3(a, b, c),GET_2_of_3(a, b, c),GET_3_of_3(a, b, c)

void main(){
    int x[3] = { SORT_3(6,2,3) };
    printf("%d, %d, %d", x[0], x[1], x[2]);
}

这适用于int并适用于C语言,但对于没有来自C ++的const_expr的字符串,它是不可能的。显然,你需要进行大量的宏观写作才能支持大量的SORT_X

答案 1 :(得分:3)

让我们考虑排序只能是0或1的数字。对于两个数字,以下代码中的SORT2可以对它们进行排序:

#define SORT2(a,b) SORT2_##a##b
#define SORT2_00 0,0
#define SORT2_01 0,1
#define SORT2_10 0,1
#define SORT2_11 1,1

这当然可以扩展到更大的范围和更多的论点。

答案 2 :(得分:0)

实际上,在编译时不能对C进行排序(至少如果要对足够大量的编译时常量整数进行排序;在这种情况下有300个宏或名为SORT_1的函数,{ {1}},... SORT_2不实用,除非你生成这些你不想要的函数或宏,但是......

实用的方法是使用您自己的或其他预处理器(例如gpp)并让它进行排序。或者简单地说,在一些包含的文件中包含数字并生成已排序的文件(例如,使用SORT_300make的{​​{1}}规则)

您还可以考虑使用LTO优化的awk,使用link-time-optimization与LTO编译的libc进行关联。这通常不是AFAIK,并且您无法保证编译器足够智能 - 足以内嵌您的LTO sort等...(AFAIK,当前的C编译器不这样做)。

如果使用最近的GCC(2015年3月的4.8,4.9或5.0)进行编译,您可以自定义它(例如使用MELT或使用您自己的C ++插件)来定义{{1 (或者可能是一些qsort)来完成这项工作。这是编译器特定的(可能意味着几天的工作,除非你已经知道MELT)

最简单的方法是接受稍微复杂的构建步骤。这不是什么大不了的事。