面试题中遇到的一个C语言switch语句的题目

这或许是很少见的用法,但我现在终于接受了一个事实:面试里出现的题目经常是极其恶心的代码,在实际工作中或许永远也见不到的那种.这是上个星期五土豆同学去参加的一个笔试里碰到的题,在这里记下来留作纪念.

问题: 下面的foo()的作用是什么?
#include <stdio.h>
#include <malloc.h>

void foo(char* a, char* b, int len) {
switch (len & 0x7) {
default: {
while (len > 7) {
len -= 8; *a++ = *b++;
}
case 7: *a++ = *b++;
case 6: *a++ = *b++;
case 5: *a++ = *b++;
case 4: *a++ = *b++;
case 3: *a++ = *b++;
case 2: *a++ = *b++;
case 1: *a++ = *b++;
}
}
}

void main(void) {
int i;
int len = 26;
char* a = (char*)malloc(100);
char* b = "abcdefghijklmnopqrstuvwxyz\0";

for (i = 0; i < 100; i++) {
a[i] = '\0';
}
foo(a, b, len); /* a = "ab\0"; */
printf("%s\n%s", a, b);
}


foo()的内容尽量保持"原样"呈现.没错,那default标签后有对诡异的大括号,迷惑力极高.我一开始也中招了.
这题的意义是,C/C++的switch statement中,case/default标签无论出现在哪里都没关系,都能按照switch语义根据条件跳转到对应标签后执行.简单点说,在这题里的default后的那对大括号加不加是等价的,所以那个while循环不会被执行,而这个switch的意义就是把b中0到len % 8 - 1的内容复制到a中...

你中招了么? ^ ^

同样的情况在Java中就不会出现,因为Java中的switch statement不允许跨case的block,上面的default后的大括号就是非法的了.这段代码在Java中的等价物是:
public class Test {

public static void main(String[] args) {
int i;
int len = 26;
char[] a = new char[100];
char[] b = "abcdefghijklmnopqrstuvwxyz".toCharArray();

for (i = 0; i < 100; i++) {
a[i] = ' ';
}
foo(a, b, len); // a = "ab\0"; // length = len % 8
System.out.printf("%s\n%s", new String(a), new String(b));
}

static void foo(char[] a, char[] b, int len) {
int cursor = 0;
switch (len & 0x7) {
default: //{
while (len > 7) {
len -= 8; a[cursor] = b[cursor]; cursor++;
}
case 7: a[cursor] = b[cursor]; cursor++;
case 6: a[cursor] = b[cursor]; cursor++;
case 5: a[cursor] = b[cursor]; cursor++;
case 4: a[cursor] = b[cursor]; cursor++;
case 3: a[cursor] = b[cursor]; cursor++;
case 2: a[cursor] = b[cursor]; cursor++;
case 1: a[cursor] = b[cursor]; cursor++;
//}
}
}
}

不要被诡异的缩进迷惑了,实际上我应该把case label全部对齐到跟default在同一缩进上,只是为了保持"迷惑力"才写成现在这样...
关于Java的语句语法,可以参考语言规范: http://java.sun.com/docs/books/jls/second_edition/html/statements.doc.html#35518

C#中的switch statement则更加严格,在Java的基础上外加不允许fall-through cases,所以上面的switch问题无法在C#中再现.

D的switch statement的行为与C/C++类似,不详细说了.
[code]void foo(char* a, char* b, int len) {
switch (len & 0x7) {
default: {
while (len > 7) {
len -= 8; *a++ = *b++;
}
case 7: *a++ = *b++;
case 6: *a++ = *b++;
case 5: *a++ = *b++;
case 4: *a++ = *b++;
case 3: *a++ = *b++;
case 2: *a++ = *b++;
case 1: *a++ = *b++;
}
}
}

void main(char[][] args) {
int i;
int len = 26;
char[100] a;
char[26] b = "abcdefghijklmnopqrstuvwxyz";

foreach (ref char c; a) {
c = '\0';
}

foo(&a[0], &b[0], len);
printf("%.*s\n%.*s", a, b);
}[/code]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值