作为我工作的一部分,我偶尔会被要求评估编程职位的候选人。我最近在我的桌面上传递了一段代码片段,我的第一个想法是我不确定这样的代码甚至会再次编译。但编译它确实如此,它也可以。
任何人都可以解释为什么以及如何运作?任务是提供一个函数来排序五个整数值。
void order5(arr) int *arr; {
int i,*a,*b,*c,*d,*e;
a=arr,b=arr+1,c=arr+2,d=arr+3,e=arr+4;
L1: if(*a >*b){*a^=*b;*b^=*a;*a^=*b;}
L2: if(*b >*c){*b^=*c;*c^=*b;*b^=*c;goto L1;}
L3: if(*c >*d){*c^=*d;*d^=*c;*c^=*d;goto L2;}
if(*d >*e){*d^=*e;*e^=*d;*d^=*e;goto L3;}
}
现在我可以看到这种方法的缺点(1970年以后出生的人缺乏可读性和可维护性),但是有人能想到任何优势吗?我犹豫不决,但是,在我们决定是否将这个人带回第2轮之前,我想知道它是否具有除了工作保障之外的任何救赎功能。
答案 0 :(得分:6)
这是一个完全展开的冒泡排序,其中XOR-swap技巧以内联方式表示。我用几个不同的选项编译它,希望它产生一些很棒的紧凑代码,但它真的不那么令人印象深刻。我投入了一些__restrict__
关键字,以便编译器知道*a
中没有一个可以互为别名,这确实有点帮助。总的来说,我认为尝试的聪明程度远远超出了规范,编译器实际上根本没有很好地优化代码。
我认为这里唯一的优点是新颖性。它确实引起了你的注意!对于滥用更多现代技术,比如使用MMX / SSE或GPU进行排序,或使用5个线程来解决它试图将其元素插入到正确的位置,我会更加印象深刻。或者可能是外部合并排序,以防万一5元素数组不适合核心。
答案 1 :(得分:5)
xor技巧只是交换两个整数。 goto是模仿循环。好处?除了展示你可以编写的代码混淆之外什么都没有。 function()之后的参数是不推荐使用的功能。手头有一个阵列,有五个不同的指针指向阵列的每个元素,这太可怕了。总结一下:哎呀! :)
答案 2 :(得分:1)
对于五个项目,这是Gnome sort的一个棘手的实现。
这是怎么回事 花园侏儒排序一排花 盆。基本上,他看着 旁边的花盆和他 前一个;如果他们在右边 为了让他向前迈出一步, 否则他交换他们并迈出第一步 锅倒了。边界条件:如果 没有以前的锅,他走了 前锋;如果旁边没有锅 他,他已经完成了。
“向前迈出一步”是通过下降到if
来完成的。每次异或交换后立即goto
执行“向后踩一个锅”。
答案 3 :(得分:1)
你不能因为这样的答案而解雇某人。它本可以用舌头提供。
这个问题非常人为,引发了人为的答案。
您需要了解候选人如何解决更多现实问题。
答案 4 :(得分:1)
1970年以后出生的人缺乏可读性和可维护性
1970年以前出生的人是否更善于维护不可读的代码呢?如果是这样,这很好,因为我是,它只能是一个卖点。
在我们决定是否将此人带回第2轮之前,我想知道作者是否有超出工作保障的任何赎回功能。
代码有否一个兑换功能 s 。它奇怪地使用xor交换技术,其唯一潜在的兑换功能是节省整数的堆栈空间。然而,即使这被定义的五个指针和未使用的int否定了。它也没有使用逗号运算符。
通常情况下,我也会说“goto,yuck”,但在这种情况下,一旦你理解了使用的排序算法,就会以相当优雅的方式使用它。事实上,你可以说它使得gnome排序算法比使用索引变量更清晰(除了它不能推广到n个元素)。所以你有兑换功能,它让goto看起来很好:)
至于“你是否将候选人带回第二次面试”。如果代码片段附有详细的注释,解释算法如何工作以及作者使用它的动机,我肯定会说是的。如果没有,我可能会打电话给他并问这些问题。
注意,代码片段使用K& R样式参数声明。这意味着作者可能没有在C中编程10到15年,或者他将其复制到互联网上。