• 嵌入式C语言经典笔试题


    简答

    如何判断一段程序是由 C 编译程序还是由 C++编译程序编译的?

    #ifdef __cplusplus
    cout<<"c++";
    #else
    cout<<"c";
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5

    用两个栈实现一个队列的功能?要求给出算法和思路!

    入队:
    将新元素 push 入栈 A;
    出队:
    (1)判断栈 B 是否为空;
    (2)如果不为空,则将栈 A 中所有元素依次 pop 出并 push 到栈 B;
    (3)将栈 B 的栈顶元素 pop 出;

    位操作(Bit manipulation)

    用 #defines 和 bit masks 操作。这是一个有极高可移植性的方法,是应该被用到的方法。最佳的解决方案如下:

    #define BIT3 (0x1 << 3)
    static int a;
    void set_bit3(void)
    {
    	a |= BIT3;
    }
    void clear_bit3(void)
    {
    	a &= ~BIT3;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    访问固定的内存位置(Accessing fixed memory locations)

    嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为 0x67a9 的整型变量的值为 0xaa66。编译器是一个纯粹的 ANSI 编译器。写代码去完成这一任务。这一问题测试你是否知道为了访问一绝对地址把一个整数强制转换

    int *ptr;
    ptr = (int *)0x67a9;
    *ptr = 0xaa66;
    
    A more obscure approach is:
    一个较晦涩的方法是:
    *(int * const)(0x67a9) = 0xaa55;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    中断(Interrupts)

    中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准 C 支持中断。具代表事实是,产生了一个新的关键字 __interrupt。下面的代码就使用了__interrupt 关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。

    __interrupt double compute_area (double radius)
    {
    double area = PI * radius * radius;
    printf("\nArea = %f", area);
    return area;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这个函数有太多的错误了,以至让人不知从何说起了:

    1. ISR 不能返回一个值。如果你不懂这个,那么你不会被雇用的。

    2. ISR 不能传递参数。如果你没有看到这一点,你被雇用的机会等同第一项。

    3. 在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的寄存器入栈,有些处理器/编译器就是不允许在 ISR 中做浮点运算。 此外,ISR 应该是短而有效率的,在 ISR 中做浮点运算是不明智的

    4. 与第三点一脉相承,printf()经常有重入和性能上的问题。如果你丢掉了第三和第四点,我不会太为难你的。不用说,如果你能得到后两点,那么你的被雇 用前景越来越光明了。

    动态内存分配(Dynamic memory allocation)

    char *ptr;
    if ((ptr = (char *)malloc(0)) == NULL)
    puts("Got a null pointer");
    else
    puts("Got a valid pointer");
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这是一个有趣的问题。最近在我的一个同事不经意把 0 值传给了函数 malloc,得到了一个合法的指针之后,我才想到这个问题。这就是上面的代码,该代码的输出是"Got a valid pointer"。我用这个来开始讨论这样一问题,看看被面试者是否想到库例程这样做是正确。得到正确的答案固然重要,但解决问题的方法和你做决定的基本原理更重要些。

    Typedef

    Typedef 在 C 语言中频繁用以声明一个已经存在的数据类型的同义字。也可
    以用预处理器做类似的事。例如,思考一下下面的例子:
    #define dPS struct s *
    typedef struct s * tPS;

    第一个扩展为struct s * p1, p2;上面的代码定义 p1 为一个指向结构的指,p2 为一个实际的结构,这也许不是你
    想要的。第二个例子正确地定义了 p3 和 p4 两个指针。

    -写一个“标准”宏交换两个参数值的宏定义为

    #define SWAP(a,b)\
    (a)=(a)+(b);\
    (b)=(a)-(b);\
    (a)=(a)-(b);
    
    • 1
    • 2
    • 3
    • 4

    输入两个参数,输出较小的一个

    #define MIN(A,B) ((A) < (B))? (A) : (B))
    
    • 1

    表明 1 年中有多少秒(忽略闰年问题)

    #define SECONDS_PER_YEAR (60 * 60 *24 * 365)UL
    
    • 1
    #define DOUBLE(x) x+x 
    #define DOUBLE(x) ((x)+(x))
    
    • 1
    • 2

    已知一个数组 table,用一个宏定义,求出数据的元素个数

    #define NTBL (sizeof(table)/sizeof(table[0]))
    
    • 1

    一个单向链表,不知道头节点,一个指针指向其中的一个节点,问如何删除这个指针指向的节点?

    将这个指针指向的 next 节点值 copy 到本节点,将 next 指向 next->next,并随后删除原 next 指向的节点。

    编程题:

  • 相关阅读:
    LeetCode-61-旋转链表
    代码随想录算法训练营Day35 | 贪心算法(4/6) LeetCode 860.柠檬水找零 406.根据身高重建队列 452. 用最少数量的箭引爆气球
    mac本安装Frida
    Springboot中国古代史在线学习网站毕业设计源码260839
    IT项目管理成功的技巧通常有哪些?
    vue3+vite与vue2+webpack 分别配置环境变量
    Oracle(11)Managing Tables
    如何在IIS7里设置实现访问.txt文件是下载模式
    JS哈希表系列
    SoftwareTest4 - 咋设计一个好的测试用例
  • 原文地址:https://blog.csdn.net/liqifff/article/details/126926329