一、C/C++题目
1.1.strcat、strncat、strcmp、strcpy,那些会导致内存溢出?如何改进?
- strcmp:与内存溢出没有关系,其功能为比较两个字符串是否相等。
- strcpy:把源字符串拷贝到目的内存中,如果源字符串过长,目标内存可能不够用,造成内存溢出。使用strcpy_s(char *dest, int size, const char *src)指定目的内存的大小进行改进。
- strcat:把一个字符串接到另一个字符串的后面,如果目的内存不足,容易照成越界。strncat()虽然可以指定连接的字符个数,但是函数在内部使用内存时,也没有做内存越界的判断。
1.2.动态内存分配
malloc()
和free()
是C/C++的库函数,返回值为空指针,需要进行强制类型转换,并且指定需要分配的内存大小new
和delete
是C++关键字,返回值是对象类型的指针,无需指定内存块的大小编译器可以自动分配内存。
malloc:
#include <iostream>
using namespace std;int main()
{int *p1 = (int *)malloc(sizeof(int)); // 分配一个int内存空间free(p1);p1 = NULL;return 0;
}
new:
#include <iostream>
using namespace std;int main()
{int *p1 = new int; // 分配一个int内存空间int *p2 = new int[20]; // 创建一个整型数组,分配20个int空间int *p3 = new int(10); // 赋初值,*p3 = 10delete p1; // 释放p1delete[] p2; // 释放p2p1 = NULL;p2 = NULL;return 0;
}
1.3.static的用法
- 修饰局部变量:使其变为静态存储方式(静态数据区),局部变量在自定义函数执行完成之后不会被释放,而是继续保留在内存中,相当于全局变量。
- 修饰全局变量:使其只在本文件中有效,而在其他文件中不可用被调用,提高程序的健壮性。
- 修饰函数:使其只在本文件中有效,而在其他文件中不可用被调用,提高程序的健壮性。
1.4.const的用法:
- 修饰常量:定义时就进行初始化,之后不能被修改
- 修饰形参:func(const int a);该形参在函数里不能被改变
- 被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。
1.5.volatile作用和用法:
volatile:adj. 易变的
主要作用:防止编译的时候被优化。
- 编译器在很多时候为了提升程序的运行效率,会删除一些没用的代码,直接从寄存器或缓存中读取变量的值。因为从寄存器或者缓存中取值速度要比内存快。如果这个变量是共享数据,或者有可能被中断等程序修改,此时读到的数据可能跟内存中的数据就有可能不一致,接下来就会导致一系列的问题。
- 在变量的前面加上volatile关键字,告诉编译器这个变量是不稳定的,不管编译器怎么优化,每次都从内存中读数据。
- 常用于操作硬件或多线程中被几个任务共享的变量
1.6 const常量与#define的区别
- const定义常量,在编译时会进行类型检查,存放在内存的静态区域,在程序运行过程中const常量只有一个拷贝。
- #define定义的常量没有数据类型的检查,用一个字符串代替数字。#define所定义的宏变量在预处理阶段的时候进行替换,在程序中使用到该常量的地方进行拷贝替换。所消耗的内存比const变量多。
1.7 sizeof和strlen
- sizeof:计算字符串或数组,在内存中的字节数,计算结果包含\0
- strlen:只对字符串有效,计算字符串的长度,计数结果不包括\0。
#include <iostream>
#include <string.h>
using namespace std;int main()
{int a[] = {1, 2, 3};char str1[] = "hello";cout << sizeof(a) << endl; // 数组在内存中的字节数12cout << sizeof(str1) << endl; // 字符串在内存中的字节数:6,包含 \0cout << strlen(str1) << endl; // 字符串长度 5return 0;
}
1.8 结构体字节对齐