9. 全局变量和局部变量的区别
定义:全局变量是定义在函数外部的变量,局部变量是定义在 函数内部的变量
存储位置:全局变量存储在全局区,局部变量存储在栈区
作用域:全局变量可以在程序任意位置使用,局部变量只能在函数内部使用
生命周期:全局变量的生命周期为整个程序,程序结束空间释放,局部变量生命周期为本函数,函数结束空间释放
初始化:全局变量未初始化初 值为0,局部变量未初始化时值为随机值
11.memcpy和strcpy的区别?
- 拷贝内容:
- memcpy:memcpy 是用于拷贝指定大小的数据块(字节),它不会自动检测字符串结束符('\0'),因此适用于拷贝任意数据,包括字符串和非字符串数据。
- strcpy:strcpy 是用于拷贝第一个以 '\0' 结尾的字符串,它会自动拷贝整个字符串,包括字符串结束符 '\0'。
- 参数:
- memcpy:memcpy 的函数原型为 void *memcpy(void *dest, const void *src, size_t n);,其中 dest 是目标地址,src 是源地址,n 是拷贝的字节数。
- strcpy:strcpy 的函数原型为 char *strcpy(char *dest, const char *src);,其中 dest 是目标字符串的地址,src 是源字符串的地址。
- 安全性:
- memcpy:memcpy 不会检查目标地址是否足够大,如果目标地址空间不够大,可能会发生缓冲区溢出的问题,导致程序崩溃或数据损坏。因此,在使用 memcpy 时需要确保目标地址有足够的空间来容纳源数据。
- strcpy:strcpy 会自动添加符字串结束符 '\0',但如果源字符串太长,超出了目标字符串的空间,也会导致缓冲区溢出问题。因此,使用 strcpy 时应留足够的空间来·容纳源字符串。
- 性能:
- memcpy:memcpy 是按字节拷贝数据,因此在拷贝大块数据时比较高效。
- strcpy:strcpy 需要遍历整个源字符串直到遇到字符串结束符 '\0',因此在拷贝较长字符串时性能可能较差。
12. 什么是段错误?怎么解决段错误?
当程序尝试访问它没有权限访问的内存地址时
段错误通常是由以下几种情况引起的:
- 访问空指针: 当程序试图访问一个空指针所指向的内存地址时,就会发生段错误。例如,未初始化的指针或者指向已释放的内存的指针。
- 数组越界: 当程序试图访问数组越界的元素时,就会发生段错误。例如,访问数组下标小于 0 或者大于等于数组大小的元素。
- 非法内存访问: 当程序试图访问未分配的内存区域,或者试图访问系 统保留的内存区域,就会发生段错误。
- 对只读内存的写操作:当程序试图对只读内存进行写 操作时,例如对常量字符串进行修改,就会发生段错误。
要解决段错误问题,可以通过以下几种方式:
- 检查空指针: 在使用指针之前,先确保指针m不是空指针。可以使用条件语句或者断言来检查指针是否为空。
- 数组边界检查: 在访问数组元素之前,先确保访问的下标在合法的范 围内。
- 动态内存管理: 在动态分配内存(例如使用 malloc、calloc、new m等函数)后,要确保在不再使用该内存时释放它(例如使用 free、 delete 等函数)。
- 避免对只读内存进行写操作: 对于常量字符串或者是只读内存区域,避免对其进行写操作,可以使用 const 关键字来声明指向只读内存的 指针。
- 使用工具检查: 可以使用一些工具,如 Valgrind,在程序运行时检查内存错误,包括段错误、内存泄漏等。
13.什么是内存泄漏?什么是野指针?
内存泄漏(Memory Leak): 内存泄漏是指程序在动态分配内存后,未释放不再使用的内存,导致这部分内存永远无法被回收,从而造成内存的浪费。如果程序中存在内存泄漏,随着程序的执行,内存占用会逐渐增加,最终可能导致程序崩溃或系统资源耗尽。内存泄漏的常见原因包括:
- 忘记释放通过 malloc、calloc、new 等动态分配的内存。
- 在循环或迭代过程中,每次分配内存却未及时释放导致累积。
- 保存了指向动态分配内存的指针,但在后续程序中指针又指向其他位置从而丢失了释放的机会。
野指针(Wild Pointer): 野指针是指指向未知或者无效内存地址的指针。野指针通常产生于以下几种情况:
- 内存释放后未置空:指针指向的内存已经被释放,但指针没有置为 nullptr 或 NULL。
- 指针越界访问:指针指向的内存已经被释放,但程序继续使用该指针指针未初始化:指针没有初始化,即没有赋予合法的地址,指针的初始值是随机的。
编程题:
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; } |