C语言面试题/笔试题/高频面试题_2

发布于:2024-12-06 ⋅ 阅读:(106) ⋅ 点赞:(0)

9. 全局变量和局部变量的区别

定义:全局变量是定义在函数外部的变量,局部变量是定义在 函数内部的变量

存储位置:全局变量存储在全局区,局部变量存储在栈

作用域:全局变量可以在程序任意位置使用,局部变量只能在函数内部使用

生命周期:全局变量的生命周期为整个程序,程序结束空间释放,局部变量生命周期为本函数,函数结束空间释放

初始化:全局变量未初始化初 值为0,局部变量未初始化时值为随机值

11.memcpy和strcpy的区别?

  1. 拷贝内容:
  1. memcpy:memcpy 是用于拷贝指定大小的数据块(字节),它不会自动检测字符串结束符('\0'),因此适用于拷贝任意数据,包括字符串和非字符串数据。
  2. strcpy:strcpy 是用于拷贝第一个以 '\0' 结尾的字符串,它会自动拷贝整个字符串,包括字符串结束符 '\0'。
  1. 参数:
  1. memcpy:memcpy 的函数原型为 void *memcpy(void *dest, const void *src, size_t n);,其中 dest 是目标地址,src 是源地址,n 是拷贝的字节数。
  2. strcpy:strcpy 的函数原型为 char *strcpy(char *dest, const char *src);,其中 dest 是目标字符串的地址,src 是源字符串的地址。
  1. 安全性:
  1. memcpy:memcpy 不会检查目标地址是否足够大,如果目标地址空间不够大,可能会发生缓冲区溢出的问题,导致程序崩溃或数据损坏。因此,在使用 memcpy 时需要确保目标地址有足够的空间来容纳源数据。
  2. strcpy:strcpy 会自动添加字串结束符 '\0',但如果源字符串太长,超出了目标字符串的空间也会导致缓冲区溢出问题。因此,使用 strcpy 时应留足够的空间来·容纳源字符串。
  1. 性能:
  1. memcpy:memcpy 是按字节拷贝数据,因此在拷贝大块数据时比较高效。
  2. strcpy:strcpy 需要遍历整个源字符串直到遇到字符串结束符 '\0',因此在拷贝较长字符串时性能可能较差。

12. 什么是段错误?怎么解决段错误?

当程序尝试访问它没有权限访问的内存地址时

段错误通常是由以下几种情况引起的:

  1. 访问空指针: 当程序试图访问一个空指针所指向的内存地址时,就会发生段错误。例如,未初始化的指针或者指向已释放的内存的指针。
  2. 数组越界: 当程序试图访问数组越界的元素时,就会发生段错误。例如,访问数组下标小于 0 或者大于等于数组大小的元素。
  3. 非法内存访问: 当程序试图访问未分配的内存区域,或者试图访问系 统保留的内存区域,就会发生段错误。
  4. 对只读内存的写操作:当程序试图对只读内存进行写 操作时,例如对常量字符串进行修改,就会发生段错误。

要解决段错误问题,可以通过以下几种方式:

  1. 检查空指针: 在使用指针之前,先确保指针m不是空指针。可以使用条件语句或者断言来检查指针是否为空。
  2. 数组边界检查: 在访问数组元素之前,先确保访问的下标在合法的范 围内。
  3. 动态内存管理: 在动态分配内存(例如使用 malloc、calloc、new m等函数)后,要确保在不再使用该内存时释放它(例如使用 free、 delete 等函数)。
  4. 避免对只读内存进行写操作: 对于常量字符串或者是只读内存区域,避免对其进行写操作,可以使用 const 关键字来声明指向只读内存的 指针。
  5. 使用工具检查: 可以使用一些工具,如 Valgrind,在程序运行时检查内存错误,包括段错误、内存泄漏等

13.什么是内存泄漏?什么是野指针?

内存泄漏(Memory Leak): 内存泄漏是指程序在动态分配内存后,未释放不再使用的内存,导致这部分内存永远无法被回收,从而造成内存的浪费。如果程序中存在内存泄漏,随着程序的执行,内存占用会逐渐增加,最终可能导致程序崩溃或系统资源耗尽。内存泄漏的常见原因包括:

  1. 忘记释放通过 malloc、calloc、new 等动态分配的内存。
  2. 在循环或迭代过程中,每次分配内存却未及时释放导致累积。
  3. 保存了指向动态分配内存的指针,但在后续程序中指针又指向其他位置从而丢失了释放的机会。

野指针(Wild Pointer): 野指针是指指向未知或者无效内存地址的指针。野指针通常产生于以下几种情况:

  1. 内存释放后未置空:指针指向的内存已经被释放,指针没有置为 nullptr 或 NULL。
  2. 指针越界访问:‌指针指向的内存已经被释放,但程序继续使用该指针指针未初始化:指针没有初始化,即没有赋予合法的地址,指针的初始值是随机的。

编程题:

1.define比较两个数的大小

#define MIN(a, b) ((a) < (b)?(a) : (b))

2.将字符串逆序输出

void reverseString(char *str) {		
    int length = strlen(str);
    char *start = str;
    char *end = str + length - 1;

    while (start < end) {
        char temp = *start;
        *start = *end;
        *end = temp;

        start++;
        end--;
    }
}

int main() {
    char str[] = "Hello, World!";
    printf("原始字符串:%s\n", str);

    reverseString(str);
    printf("逆序输出:%s\n", str);

    return 0;
}

3.冒泡排序

void bubbleSort(int arr[], int n) {
    int i, j;
    for (i = 0; i < n-1; i++) {
        // 每次循环将最大的元素冒泡到末尾,因此每轮循环只需比较前 n-i-1 个元素
        for (j = 0; j < n-i-1; j++) {
            if (arr[j] > arr[j+1]) {
                // 如果前一个元素大于后一个元素,则交换它们的位置
                int temp = arr[j];     //arr[j] ^= arr[j + 1];
                arr[j] = arr[j+1];     //arr[j + 1] ^= arr[j];
                arr[j+1] = temp;       //arr[j] ^= arr[j + 1];
            }
        }
    }
}

4.strlen、strcpy、strcat、strcmp

size_t my_strlen(const char *str) { 
    size_t len = 0;
    while (*str) {
        len++;
        str++;
    }

    return len;
}

char *my_strcpy(char *dest, const char *src) {
    char *temp = dest;	// 暂存dest字符串的首地址
    while (*src) {
        *dest = *src;                      
        dest++;
        src++;
    }
    *dest = '\0'; // 在目标字符串末尾加上 null 终止符
    return temp;
}

char *my_strcat(char *dest, const char *src) {
    char *temp = dest;                                                                                                                        
    // 移动 dest 指针到目标字符串的末尾
    while (*dest) {
        dest++;
    }

    // 将源字符串复制到目标字符串的末尾
    while (*src) {
        *dest = *src;
        dest++;                                                                 
        src++;
    }

    // 添加目标字符串的 null 终止符
    *dest = '\0';

    return temp;
}

#include <stdio.h>

int my_strcmp(const char *str1, const char *str2) {
    while (*str1 && *str2) {
        if (*str1 != *str2) {
            return *str1 - *str2;
        }
        str1++;
        str2++;
    } 
    
    // 如果两个字符串长度不等,返回长度差值
    return *str1 - *str2;
}

int main() {
    const char *str1 = "apple";
    const char *str2 = "banana";

    int result = my_strcmp(str1, str2);

    if (result < 0) {
        printf("%s 小于 %s\n", str1, str2);
    } else if (result == 0) {
        printf("%s 等于 %s\n", str1, str2);
    } else {
        printf("%s 大于 %s\n", str1, str2);
    }

    return 0;
}

5.打印杨辉三角前10行

#include <stdio.h>
int main(int argc, char const *argv[])
{
    int a[10][10] = {0}, i, j;



    for (i = 0; i < 10; i++)
    {
        a[i][0] = 1;
        for (j = 1; j <= i; j++)
            a[i][j] = a[i - 1][j] + a[i - 1][j - 1];
    }
    for (i = 0; i < 10; i++)
    {
        for (j = 0; j <= i; j++)
            printf("%-5d", a[i][j]);
        putchar('\n');
    }
    return 0;
}运行上述代码,将会输出杨辉三角的前10行:

Copy code
1 
1 1 
1 2 1 
1 3 3 1 
1 4 6 4 1 
1 5 10 10 5 1 
1 6 15 20 15 6 1 
1 7 21 35 35 21 7 1 
1 8 28 56 70 56 28 8 1 
1 9 36 84 126 126 84 36 9 1
每一行的数字都代表一个组合数,它是由 C(n, k) 组成,其中 n 为行数减1,k 为列数减1。在这个例子中,C(n, k) = triangle[n][k]。

6.atoi函数自定义

7.定义一个函数计算一个字节里(byte)里面有多少bit被置1/

int count(int x+)

{

int num=0;

for (int i = 0; i < 8; i++)//一个字节是8位

{

if((x&(1<<i))!=0)

num++;

}

return num;

}


网站公告

今日签到

点亮在社区的每一天
去签到