C语言笔试题常见考点有哪些?

99ANYc3cd6
预计阅读时长 31 分钟
位置: 首页 C语言 正文

C语言开发工程师 笔试题

考试时间: 120分钟 总分: 100分

c语言开发工程师笔试题
(图片来源网络,侵删)

第一部分:选择题 (每题3分,共30分)

  1. sizeofstrlen,以下说法正确的是? A. sizeof 是一个函数,strlen 是一个运算符。 B. sizeof 计算的是类型或变量所占的内存字节数,strlen 计算的是字符串的长度(不包括结尾的 \0)。 C. 对于一个空字符串 char str[] = "";sizeof(str) 的结果是0。 D. sizeof 的结果在编译时确定,而 strlen 的结果在运行时确定。

  2. 在32位系统上,sizeof("Hello, World!") 的值是? A. 11 B. 12 C. 13 D. 取决于编译器

  3. 以下关于 const 的描述,错误的是? A. const int *p; 表示 p 指向的内容不能被修改,但 p 本身可以指向其他地址。 B. int * const p; 表示 p 本身是常量,不能指向其他地址,但指向的内容可以被修改。 C. const int * const p; 表示 p 和它指向的内容都不能被修改。 D. const 修饰的变量必须在声明时初始化。

  4. 以下代码的输出是什么?

    c语言开发工程师笔试题
    (图片来源网络,侵删)
    #include <stdio.h>
    int main() {
        int a = 5;
        int b = 10;
        int *p = &a;
        int *q = &b;
        p = q;
        *p = 20;
        printf("%d, %d\n", a, b);
        return 0;
    }

    A. 5, 10 B. 5, 20 C. 20, 10 D. 20, 20

  5. 对于结构体 struct S { char c; int i; };,在大多数32位系统上,sizeof(struct S) 的值最可能是? A. 5 B. 7 C. 8 D. 12

  6. 以下哪个宏定义是安全的(不会产生副作用)? A. #define MAX(a, b) ((a) > (b) ? (a) : (b)) B. #define SQUARE(x) (x * x) C. #define ADD_TO(a, b) (a += b) D. #define STRCPY(d, s) strcpy(d, s)

  7. 以下哪个不是C语言的关键字? A. extern B. typedef C. sizeof D. function

    c语言开发工程师笔试题
    (图片来源网络,侵删)
  8. 在C语言中,以下哪个函数可以用来动态分配一块连续的内存空间? A. malloc() B. free() C. calloc() D. realloc() E. 以上都是

  9. 以下代码的输出是什么?

    #include <stdio.h>
    int main() {
        int i = 0;
        for (; i < 5; ++i) {
            if (i == 2) continue;
            printf("%d ", i);
        }
        return 0;
    }

    A. 0 1 2 3 4 B. 0 1 3 4 C. 0 1 2 4 D. 0 1 2 3

  10. volatile 关键字的主要作用是? A. 优化代码,提高运行效率。 B. 声明一个变量是易变的,防止编译器进行不必要的优化。 C. 声明一个变量是只读的。 D. 确保变量在多线程环境下的原子性访问。


第二部分:填空题 (每空2分,共20分)

  1. 在C语言中,FILE * 是一个指向__类型的指针,用于文件操作。
  2. 函数指针 int (*func_ptr)(int, char*); 表示一个指向__的指针,该函数返回一个 int,并接受一个 int 和一个 char* 作为参数。
  3. enum Color { RED, GREEN, BLUE }; 中,RED 的默认值是__
  4. 在Linux环境下,使用 fork() 函数创建子进程后,子进程的 fork() 返回值是__,父进程的 fork() 返回值是__
  5. 为了避免头文件被重复包含,通常使用__宏和__宏进行保护。
  6. strcat 函数的作用是__,它要求目标字符串必须有足够的空间以容纳连接后的结果,否则会导致__
  7. static 关键字修饰局部变量时,会使该变量的生命周期__(延长/缩短)为整个程序的生命周期。

第三部分:简答题 (每题10分,共20分)

  1. 简述C语言中 structunion 的区别。
  2. 简述C语言中 malloccalloc 的主要区别。

第四部分:编程题 (共30分)

1:实现一个简单的字符串反转函数 (10分)* 请编写一个函数 `void reverse_string(char str),将输入的字符串str原地反转,要求不能使用任何库函数(如strlen),并确保字符串以\0 2:找出数组中的最大值和次大值 (15分)** 请编写一个函数void find_two_largest(int arr[], int size, int max, int second_max),该函数能从整数数组arr中找出最大值和次大值,并通过指针参数maxsecond_max返回结果,要求算法的时间复杂度为 O(n)。 3:实现一个单链表的逆序 (5分)** 请用C语言定义一个单链表节点,并编写一个函数struct ListNode reverse_list(struct ListNode head)`,将一个单链表原地逆序。



参考答案与解析

第一部分:选择题

  1. B

    • 解析: sizeof 是一个运算符,而不是函数,它在编译时计算大小。strlen 是一个库函数,它在运行时遍历字符串直到遇到 \0 来计算长度,选项A错误。sizeof(str) 计算的是数组 str 所占的总空间,包括结尾的 \0,所以结果是1,选项C错误。sizeof 的结果在编译时确定,但 strlen 的结果在运行时确定,选项D正确,但B选项的描述更全面和准确,因此B是最佳答案。
  2. C

    • 解析: sizeof 计算的是字符串字面量所占的内存空间。"Hello, World!" 包含11个可见字符和1个字符串结束符 \0,总共12个字节,在32位或64位系统上,一个 char 占1个字节,所以结果是12。
  3. D

    • 解析: const 修饰的变量可以在声明时初始化,也可以之后通过指针等方式间接修改(const 修饰的不是指针本身)。const int a; 之后 a = 10; 是错误的,但 int b = 5; const int *p = &b; *p = 10; 也是错误的,但全局 const 变量如果不初始化,编译器会默认初始化为0,所以D的说法过于绝对,是错误的,A、B、C都是对 const 正确的用法描述。
  4. D

    • 解析: p 最初指向 ap = q; 使得 p 也指向了 b 的地址。*p = 20; 就是修改 p 所指向的内容,即修改 b 的值为20。a 的值没有改变,仍然是5。printf 打印的是 ab,所以输出是 5, 20注意: 原题有误,*p = 20; 修改的是 b,所以正确输出应为 5, 20,但选项中没有这个答案,最接近的D是笔误,或者原题意图是 *q = 20;,我们按标准逻辑分析,正确答案应为 B. 5, 20,如果选项D是 5, 20,则选D,这里我们假设题目有笔误,B是正确答案。
  5. C

    • 解析: 这考察的是内存对齐,为了提高内存访问效率,编译器会进行内存对齐。char 通常对齐到1字节,int 通常对齐到4字节,结构体 struct S 中,char c 占1字节,为了使 int i 能从4字节的边界开始,编译器会在 c 后面填充3个字节,i 占4字节,所以总共是 1 + 3 + 4 = 8 字节。
  6. A

    • 解析: A选项是安全的,因为它使用了括号,避免了 MAX(a++, b) 这样的调用导致 a 被多次自增,B选项不安全,SQUARE(a+1) 会变成 a+1 * a+1,结果是 a + a + 1,C选项有副作用,调用 ADD_TO(a, b) 会永久改变 a 的值,D选项没有做类型检查,不安全。
  7. D

    • 解析: extern, typedef, sizeof 都是C语言的关键字。function 不是C语言的关键字。
  8. E

    • 解析: malloc 分配指定大小的内存。calloc 分配指定数量和大小的内存,并初始化为0。realloc 重新调整已分配内存的大小。free 释放内存,它们都是用于动态内存管理的函数。
  9. B

    • 解析: for 循环从 i=0 开始,当 i=2 时,continue 语句会跳过本次循环的剩余部分(即 printf),直接进入下一次循环。i=2 不会被打印。
  10. B

    • 解析: volatile 告诉编译器,这个变量的值可能会在编译器未察觉的情况下被改变(硬件、多线程或信号处理程序),编译器不会对其进行优化,每次使用都会从内存中重新读取,以保证数据的“新鲜”。

第二部分:填空题

  1. FILE (或 struct _IO_FILE)
  2. 一个函数 (或 一个返回int,参数为int和char*的函数)
  3. 0 (枚举成员的默认值从0开始递增)
  4. 0 (子进程的返回值), 子进程的PID (父进程的返回值)
  5. #ifndef, #define (或 #pragma once)
  6. 将源字符串连接到目标字符串的末尾, 缓冲区溢出 (Buffer Overflow)
  7. 延长

第三部分:简答题

  1. structunion 的区别:

    • 内存占用: struct 是结构体,它的各个成员在内存中是依次存放的,总大小是其所有成员大小之和(考虑对齐)。union 是联合体,它的所有成员共享同一块内存空间,总大小是其最大成员的大小。
    • 数据访问: struct 的所有成员可以同时被访问和赋值,互不影响。union 在任意时刻,只有一个成员是有效的,对其中一个成员的赋值会覆盖其他成员的值。
    • 用途: struct 用于将不同类型的数据组合成一个整体,用于描述一个复杂的对象。union 用于在不同的数据类型之间“复用”内存,例如需要存储多种类型数据中的一种,或者需要查看同一块内存的不同数据表示(如网络字节序转换)。
  2. malloccalloc 的区别:

    • 参数不同: malloc 只有一个参数,即需要分配的内存字节数。calloc 有两个参数,分别是元素的个数和每个元素的大小。
    • 内存初始化: malloc 分配的内存是未初始化的,里面是随机的垃圾值。calloc 分配的内存会被初始化为全0。
    • 实现(: calloc 内部通常会先调用 malloc 分配内存,然后再使用 memset 或类似函数将这块内存清零。

第四部分:编程题

1:实现一个简单的字符串反转函数**

#include <stdio.h>
void reverse_string(char *str) {
    if (str == NULL) {
        return;
    }
    char *start = str;
    char *end = str;
    // 1. 找到字符串的末尾 (不包括 '\0')
    while (*end != '\0') {
        end++;
    }
    end--; // end现在指向最后一个字符
    // 2. 交换头尾字符,并向中间移动
    while (start < end) {
        char temp = *start;
        *start = *end;
        *end = temp;
        start++;
        end--;
    }
}
int main() {
    char str[] = "Hello, World!";
    printf("Original: %s\n", str);
    reverse_string(str);
    printf("Reversed: %s\n", str);
    return 0;
}

2:找出数组中的最大值和次大值**

#include <stdio.h>
#include <limits.h> // 为了 INT_MIN
void find_two_largest(int arr[], int size, int *max, int *second_max) {
    if (size < 2) {
        // 数组元素不足,无法找到两个最大值
        *max = *second_max = INT_MIN; // 或设置错误码
        return;
    }
    // 初始化 max 和 second_max
    if (arr[0] > arr[1]) {
        *max = arr[0];
        *second_max = arr[1];
    } else {
        *max = arr[1];
        *second_max = arr[0];
    }
    // 从第三个元素开始遍历
    for (int i = 2; i < size; i++) {
        if (arr[i] > *max) {
            // 当前元素比最大值还大,更新次大值为原最大值,最大值为当前元素
            *second_max = *max;
            *max = arr[i];
        } else if (arr[i] > *second_max && arr[i] != *max) {
            // 当前元素介于最大值和次大值之间,更新次大值
            *second_max = arr[i];
        }
    }
}
int main() {
    int arr[] = {12, 35, 1, 10, 34, 1};
    int size = sizeof(arr) / sizeof(arr[0]);
    int max, second_max;
    find_two_largest(arr, size, &max, &second_max);
    printf("The largest element is %d\n", max);
    printf("The second largest element is %d\n", second_max);
    return 0;
}

3:实现一个单链表的逆序**

#include <stdio.h>
#include <stdlib.h>
// 定义链表节点
struct ListNode {
    int val;
    struct ListNode *next;
};
struct ListNode* reverse_list(struct ListNode *head) {
    struct ListNode *prev = NULL;
    struct ListNode *current = head;
    struct ListNode *next = NULL;
    while (current != NULL) {
        // 保存下一个节点
        next = current->next;
        // 将当前节点的next指向前一个节点
        current->next = prev;
        // prev 和 current 向后移动
        prev = current;
        current = next;
    }
    // 当循环结束时,prev指向新的头节点
    return prev;
}
// 辅助函数:创建链表
struct ListNode* create_list(int arr[], int size) {
    if (size == 0) return NULL;
    struct ListNode *head = (struct ListNode*)malloc(sizeof(struct ListNode));
    head->val = arr[0];
    struct ListNode *current = head;
    for (int i = 1; i < size; i++) {
        current->next = (struct ListNode*)malloc(sizeof(struct ListNode));
        current = current->next;
        current->val = arr[i];
        current->next = NULL;
    }
    return head;
}
// 辅助函数:打印链表
void print_list(struct ListNode *head) {
    struct ListNode *current = head;
    while (current != NULL) {
        printf("%d -> ", current->val);
        current = current->next;
    }
    printf("NULL\n");
}
int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int size = sizeof(arr) / sizeof(arr[0]);
    struct ListNode *head = create_list(arr, size);
    printf("Original list: ");
    print_list(head);
    head = reverse_list(head);
    printf("Reversed list: ");
    print_list(head);
    return 0;
}
-- 展开阅读全文 --
头像
数据库织梦文章链接如何生成?
« 上一篇 04-27
dede源码安装步骤是怎样的?
下一篇 » 04-27

相关文章

取消
微信二维码
支付宝二维码

目录[+]