`
RednaxelaFX
  • 浏览: 3049312 次
  • 性别: Icon_minigender_1
  • 来自: 海外
社区版块
存档分类
最新评论

面试题中遇到的一个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++类似,不详细说了.
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);
}
分享到:
评论
3 楼 zhczjx 2016-08-31  
   Mark一下 找了好久终于找到算法或者说这种写法的名字 Duff's Device。达夫设备 
2 楼 RednaxelaFX 2007-10-25  
啊,确实。8的倍数比较特别,我把这情况给漏了。8的倍数的时候,是7 + ( n / 8 )...多谢提醒 ^ ^

不过后来土豆告诉我,他把题记错了。这题实际上是这样的:
#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 = 0;      
    char* a = (char*)malloc(100);      
    char* b = "abcdefghijklmnopqrstuvwxyz\0";      
     
    for (i = 0; i < 100; i++) {      
        a[i] = '\0';      
    }      
    foo(a, b, len);    
    printf("%s\n%s", a, b);      
}

而这实际上不过是很常见的一种while循环展开而已。更出名的一种变体是这样的:
int q = ( n + 7 ) / 8;   
switch ( n % 8 ) {   
case 0:         do {    foo( );          // Great C hack, Tom,   
case 7:                 foo( );          // but it's not valid here.   
case 6:                 foo( );   
case 5:                 foo( );   
case 4:                 foo( );   
case 3:                 foo( );   
case 2:                 foo( );   
case 1:                 foo( );   
                } while (--q > 0);   
}

(摘自Java Language Specification, 3rd Edition)
1 楼 afanti2005 2007-10-24  
你输入一个能被8 len 的数试试

相关推荐

    linux c语言面试题

    【Linux C语言面试题】是针对C语言编程和Linux系统操作的面试准备资料,涵盖了从基础知识到高级概念的多个方面。这些题目旨在测试面试者对C语言的理解深度、编程技巧以及在Linux环境下解决问题的能力。以下是一些...

    C语言面试题总汇.doc 大量C语言面试题汇总,附带答案

    C 语言面试题总汇 本文档将详细介绍 C 语言面试题总汇,涵盖了 C 语言的各种知识点,包括静态变量、指针、引用、实时系统、堆栈溢出、虚函数、冒泡排序、网络协议、IP 地址等。 1. static 变量的用途: static ...

    嵌入式C语言面试题汇总

    嵌入式C语言面试题汇总 本文档总结了嵌入式C语言面试中的常见问题,包括基本概念、程序代码评价、编程题等。以下是本文档的详细知识点总结: 一、基本概念 1. 静态关键字的作用:静态关键字有三个明显的作用:在...

    C语言面试题大汇总 C语言面试题大汇总

    C语言面试题大汇总中涵盖了许多重要的C语言概念和技术,这些知识点是面试中常见的问题,对于理解和掌握C语言至关重要。以下是其中一些关键知识点的详细解释: 1. **`static`关键字**: - `static`用于限制变量的...

    面试题合集.zip,C语言面试题合集

    C语言是计算机编程的基础,是许多现代软件和...通过这个“面试题合集.zip”,你可以系统地复习和提升C语言的理论知识和实践技能,为你的程序员面试做好充分准备。记得不仅要理解答案,还要能灵活运用到实际编程中去。

    一个很全的面试题集合C语言面试题大全

    ### C语言面试题知识点详解 #### 一、`static` 关键字的用途 1. **改变变量的连接方式(改成内部连接)** - `static`关键字用于变量时,可以使变量具有内部链接属性,这意味着变量只能在声明它的源文件中访问。...

    面试必备c语言考试真题

    C语言的基础知识包括变量、数据类型、运算符、流程控制(如if语句、switch语句、循环结构)、函数、指针、数组、结构体等。理解这些概念及其用法是C语言学习的第一步。例如,指针是C语言的一大特色,它允许直接操作...

    C语言笔试题程序员面试题大集合

    本资料集"程序员面试题大集合"专注于C语言的笔试题,旨在帮助求职者在企业面试和笔试中脱颖而出。 首先,我们要理解C语言的基础知识。C语言是一种结构化编程语言,它提供了丰富的控制语句,如if-else、switch-case...

    C语言面试常问的一些面试题

    C语言是计算机编程的基础,尤其在面试中,掌握C语言的基本知识是至关...掌握这些基本概念对于理解和解答C语言面试题至关重要。通过深入理解并实践这些知识点,可以提高面试时的表现,为未来的职业发展奠定坚实基础。

    嵌入式研发工程师笔试试题/重解几道华为经典C语言面试题

    本文档主要围绕C语言面试题展开,涵盖了字符串、字符数组、strcpy函数、strlen函数、static变量、auto变量、switch语句等多个知识点,旨在帮助读者巩固C语言基础知识,提高编程能力。 一、字符串和字符数组 在...

    C-language-classic-title.zip_C C++ 面试题_C语言面试_c语言题

    3. 流程控制:如if语句、switch语句、for循环、while循环等,是程序逻辑构建的关键。 4. 函数:函数是C语言中的重要模块,理解函数的定义、调用、参数传递及返回值,以及函数指针的概念。 二、指针与内存管理 1. ...

    C语言面试题C语言面试题

    根据提供的文件信息,我们可以整理出一系列与C语言相关的面试题及知识点。下面将对这些知识点进行详细的阐述: ### 1. 静态变量(Static Variables) - **定义**: C语言中的静态变量是指在其作用域内保持其值不变...

    几道经典C语言面试题(华为)

    1. **Switch语句与Case穿透**:在C语言中,如果没有显式使用`break`语句,控制流会继续执行下一个`case`块,直到遇到`break`或`switch`语句的结尾。因此,当`a`等于1时,`b`会被赋值为30,然后继续执行下一条语句,...

    C语言相关面试题

    以下是一些C语言相关的面试题,旨在测试和提升你的C语言知识。 1. **基本概念** - 什么是C语言?C语言是由Dennis Ritchie在贝尔实验室开发的,它是一种面向过程的、低级的、结构化的编程语言。 - C语言的特点有...

    C程序员语言面试100题.rar_C语言100题_C语言笔试面试_C语言面试题_程序员笔试题_阿里

    《C程序员语言面试100题》是针对C语言编程技术的一份综合性的面试题集,涵盖了华为、中兴、阿里、腾讯等知名企业的常见笔试和面试问题。这份资料旨在帮助程序员深入理解和熟练掌握C语言的基础知识,以及在实际开发中...

    C语言面试题.rar

    文件"C语言面试题(1).doc"可能是文档形式的面试题集合,可能涵盖了C语言的基础知识,例如变量、数据类型、运算符、控制结构(如if语句、switch语句、循环)、函数、指针、数组、字符串、内存管理等方面的问题。...

    C语言面试题总汇附答案

    C语言面试题总汇附答案 本资源提供了详细的C语言面试题,涵盖了C语言的基础知识、数据结构、算法、网络协议等方面。通过学习这些题目,能够帮助读者更好地理解C语言的概念和应用。 一、变量和存储域 * static变量...

    C语言面试题大汇总(pdf版)

    这份“C语言面试题大汇总”PDF文档,虽然可能不是最全面的资源,但无疑能为面试者提供有价值的参考。 一、C语言基础 1. 数据类型:了解C语言中的基本数据类型,如int、char、float、double等,以及它们的存储大小...

Global site tag (gtag.js) - Google Analytics