这个排序功能是如何工作的?
作为我工作的一部分,我偶尔会被要求评估编程职位的候选人。最近我的办公桌上经过了一段代码片段,我的第一个想法是我不确定这样的代码是否还能编译。但编译确实如此,而且也能正常工作。
谁能解释一下这是为什么以及如何工作的?任务是提供一个对五个整数值进行排序的函数。
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 年后出生的人来说缺乏可读性和可维护性),但有人能想到任何优点吗?我很犹豫是否要立即驳回它,但在我们决定是否让这个人回来参加第二轮之前,我想知道除了作者的工作保障之外,它是否还有任何可取之处。
As part of my job, I'm occasionally called upon to evaluate candidates for programming positions. A code snippet recently passed across my desk and my first thoughts were that I wasn't sure code like this would even compile any more. But compile it does, and it works as well.
Can anyone explain why and how this works? The mandate was to provide a function to sort five integer values.
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;}
}
Now I can see the disadvantages of this approach (lack of readability and maintainability for anyone born after 1970) but can anyone think of any advantages? I'm hesitant to dismiss it out of hand but, before we decide whether or not to bring this person back in for round 2, I'd like to know if it has any redeeming features beyond job security for the author.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这是一种完全展开的冒泡排序,具有内联表达的异或交换技巧。我用几个不同的选项编译它,希望它能产生一些很棒的紧凑代码,但它确实没有那么令人印象深刻。我添加了一些
__restrict__
关键字,以便编译器知道*a
中没有一个可以互相别名,这确实有很大帮助。但总的来说,我认为这种聪明的尝试已经远远超出了规范,编译器实际上根本没有很好地优化代码。我认为这里唯一的优点是新颖。它肯定引起了您的注意!我会对滥用更现代的技术印象更深刻,比如使用 MMX/SSE 或 GPU 进行排序,或者使用 5 个线程,这些线程都在努力将其元素插入到正确的位置。或者可能是外部合并排序,以防 5 元素数组无法放入核心。
It's a fully unrolled bubble sort with the XOR-swap trick expressed inline. I compiled it with several different options hoping it produced some awesome compact code, but it's really not that impressive. I threw in some
__restrict__
keywords so that the compiler would know that none of the*a
could alias each other, which does help quite a bit. Overall though, I think the attempted cleverness has gone so far outside the norm that the compiler is really not optimizing the code very well at all.I think the only advantage here is novelty. It certainly caught your eye! I would have been more impressed with abuses of more modern technology, like sorting with MMX/SSE or the GPU, or using 5 threads which all fight it out to try to insert their elements into the right place. Or perhaps an external merge sort, just in case the 5 element array can't fit in core.
异或技巧只是交换两个整数。 goto 是循环的模仿。优点?除了炫耀你能写出多么令人困惑的代码之外,什么也没有。 function () 之后的参数是一个已弃用的功能。手头有一个数组,并且有 5 个不同的指针指向数组的每个元素,这太可怕了。总结一下:呸! :)
The xor trick just swaps two integers. The goto's are the imitation of the loop. Advantages? None at all except for showing off how obfuscated a code you can write. The parameter after function () is a deprecated feature. And having an array on hand and havong 5 distinct pointers pointing at each elem of the array is just horrible. To sum it up: Yuck! :)
这是对五个项目的 Gnome 排序 的扭曲实现。
“向前迈一步”是通过跳到下一个
if
来完成的。每次异或交换之后立即执行“goto”,“向后退一步”。It's a screwy implementation of Gnome sort for five items.
The "stepping one pot forward" is done by falling through to the next
if
. Thegoto
immediately after each XOR-swap does the "stepping one pot backwards."你不能因为这样的答案就立即解雇某人。它可能是半开玩笑地提供的。
这个问题是高度人为的,会引发人为的答案。
您需要了解候选人将如何解决更多现实问题。
You can't dismiss someone out of hand for an answer like this. It might have been provided tongue-in-cheek.
The question is highly artificial, prompting contrived answers.
You need to find out how the candidate would solve more real-world problems.
那么 1970 年之前出生的人是否更擅长维护不可读的代码?如果是这样,那很好,因为我就是这样,这只能是一个卖点。
该代码
没有一项兑换功能s。它奇怪地使用了异或交换技术,其唯一潜在的补救功能是节省一个整数的堆栈空间。然而,即使如此,也被定义的五个指针和未使用的 int 所否定。它还无端使用逗号运算符。通常,我也会说“goto,yuck”,但在这种情况下,一旦您了解了所使用的排序算法,它就以一种相当优雅的方式使用了。事实上,您可能会说它使 gnome 排序算法比使用索引变量更清晰(除非它不能推广到 n 个元素)。所以你就有了可取之处,它让 goto 看起来不错:)
至于“你会把候选人带回来进行第二次面试吗”。如果代码片段附有详细的注释,解释算法如何工作以及作者使用它的动机,我肯定会说是的。如果没有,我可能会打电话给他并问这些问题。
注意,代码片段使用 K&R 风格的参数声明。这意味着作者可能已经有 10 到 15 年没有用 C 编程了,或者他是从互联网上复制的。
Are people born before 1970 better at maintaining unreadable code then? If so, that's good because I was and it can only be a selling point.
The code has
noone redeeming features. It bizarrely uses the xor swap technique whose only potential redeeming feature would be saving oner integer's worth of stack space. However, even that is negated by the five pointers defined and the unused int. It also has a gratuitous use of the comma operator.Normally, I'd also say "goto, yuck", but in this case, it has been used in quite an elegant way, once you understand the sort algorithm used. In fact, you could argue that it makes the gnome sort algorithm clearer than using an index variable (except it cannot be generalised to n elements). So there you have the redeeming feature, it makes goto look good :)
As for "do you bring the candidate back for the second interview". If the code fragment was accompanied by a detailed comment explaining how the algorithm worked and the writer's motivation for using it, I'd say definitely yes. If not, I'd probably ring him up and ask those questions.
NB, the code fragment uses K&R style parameter declarations. This means the author probably hasn't programmed in C for 10 to 15 years or he copied it off the Internet.