一、malloc申请内存
1.malloc和free是c++/c语言的库函数,需要头文件支持stdlib.h;new和delete是C++的关键字,不需要头文件,需要编译器支持;
2.使用new操作符申请内存分配时,无需指定内存块的大小,编译器会根据类型信息自行计算。而malloc则需要显式地支持所需内存的大小。
3.new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无需进行类型转换,故new是符合类型安全性的操作符。而malloc内存分配成功则是返回void*,需要通过强制类型转换将void*指针转换成我们需要的类型。
4.new内存分配失败时,会抛出bad_alloc异常。malloc分配内存失败时返回NULL。
二、在1G内存的计算机中能否malloc(1.2G)?为什么?
答:是有可能申请1.2G的内存的。
解析:回答这个问题前需要知道malloc的作用和原理,应用程序通过malloc函数可以向程序的虚拟空间申请一块虚拟地址空间,与物理内存没有直接关系,得到的是在虚拟地址空间中的地址,之后程序运行所提供的物理内存是由操作系统完成的。
三、extern”C” 的作用
我们可以在C++中使用C的已编译好的函数模块,这时候就需要用到extern”C”。也就是extern“C” 都是在c++文件里添加的。
extern在链接阶段起作用(四大阶段:预处理--编译--汇编--链接)。
四、strcat、strncat、strcmp、strcpy哪些函数会导致内存溢出?如何改进?
strcpy函数会导致内存溢出。
strcpy拷贝函数不安全,他不做任何的检查措施,也不判断拷贝大小,不判断目的地址内存是否够用。
char *strcpy(char *strDest,const char *strSrc)
strcpy
将源字符串复制到目标缓冲区。如果目标缓冲区没有足够的空间,可能会导致缓冲区溢出
strcat
将源字符串追加到目标字符串的末尾。问题在于,如果目标字符串没有足够的空间容纳源字符串,会导致缓冲区溢出。#include <string.h> #include <stdio.h> void safe_strcat(char *dest, size_t dest_size, const char *src) { size_t dest_len = strlen(dest); size_t src_len = strlen(src); if (dest_len + src_len + 1 > dest_size) { fprintf(stderr, "Buffer overflow prevented!\n"); return; } strcat(dest, src); }
五、 strcpy和memcop函数的区别
memcpy拷贝函数,它与strcpy的区别就是memcpy可以拷贝任意类型的数据,strcpy只能拷贝字符串类型。
memcpy 函数用于把资源内存(src所指向的内存区域)拷贝到目标内存(dest所指向的内存区域);有一个size变量控制拷贝的字节数;
函数原型:
void *memcpy(void *dest, void *src, unsigned int count);
六、malloc
函数和calloc
函数
1.mallocpy函数
void* malloc(size_t size);
size
是要分配的字节数。- 返回值是一个指向已分配内存的指针,如果分配失败,则返回
NULL
。
由于 malloc
分配的内存未初始化,因此内存块中的内容是未定义的。
#include <stdlib.h> #include <stdio.h> int main() { int *arr; arr = (int *)malloc(10 * sizeof(int)); // 分配可以容纳10个int的内存 if (arr == NULL) { fprintf(stderr, "Memory allocation failed\n"); return 1; } // 使用内存... free(arr); // 释放内存 return 0; }
2.calloc
函数
calloc
函数用于分配内存并将其初始化为零。它的原型如下:
void* calloc(size_t num, size_t size);
num
是要分配的元素数量。size
是每个元素的大小(以字节为单位)。- 返回值是一个指向已分配内存的指针,如果分配失败,则返回
NULL
。
calloc
分配的内存块中的每个字节都被初始化为零。
#include <stdlib.h>
#include <stdio.h>
int main() {
int *arr;
arr = (int *)calloc(10, sizeof(int)); // 分配可以容纳10个int的内存,并初始化为0
if (arr == NULL) {
fprintf(stderr, "Memory allocation failed\n");
return 1;
}
// 使用内存...
free(arr); // 释放内存
return 0;
}
3. realloc函数
realloc
用于调整已分配内存块的大小,可以扩大或缩小内存块。
void* realloc(void* ptr, size_t size);
int *arr = (int *)realloc(arr, 20 * sizeof(int)); // 调整内存大小以容纳20个int
4.free函数
void free(void* ptr);
ptr
: 指向要释放内存的指针。- 没有返回值。
七、static的用法(定义和用途)
1.c语言中的static关键字
1.用static修饰局部变量:使其变为静态存储方式(静态数据区),那么这个局部变量在函数执行完成之后不会被释放,而是继续保留在内存中。
2.用static修饰全局变量:使其只在本文件内部有效,而其他文件不可连接或引用该变量。
3.用static修饰函数:对函数的连接方式产生影响,使得函数只在本文件内部有效,对其他文件是不可见的(这一点在大工程中很重要很重要,避免很多麻烦,很常见)。这样的函数又叫作静态函数。使用静态函数的好处是,不用担心与其他文件的同名函数产生干扰,另外也是对函数本身的一种保护机制。
2.C++中的关键字static关键字
1. 静态局部变量
在函数内部使用 static
关键字声明的变量是静态局部变量。静态局部变量在函数第一次调用时被初始化,并且其生命周期贯穿整个程序运行期间。
#include <iostream>
void counter() {
static int count = 0;
count++;
std::cout << "Count: " << count << std::endl;
}
int main() {
counter(); // Count: 1
counter(); // Count: 2
counter(); // Count: 3
return 0;
}
2.静态全局变量
在文件作用域(即全局作用域)使用 static
关键字声明的变量是静态全局变量。静态全局变量只在声明它的文件中可见(具有内部链接),其他文件无法访问。
// file1.cpp
static int globalVar = 42;
void printGlobalVar() {
std::cout << globalVar << std::endl;
}
// file2.cpp
extern void printGlobalVar();
int main() {
printGlobalVar(); // 42
return 0;
}
3.静态成员变量
在类中使用 static
关键字声明的变量是静态成员变量。静态成员变量在类的所有实例之间共享,且属于类而不是某个具体的实例。
#include <iostream>
class MyClass {
public:
static int staticVar;
static void printStaticVar() {
std::cout << staticVar << std::endl;
}
};
int MyClass::staticVar = 0;
int main() {
MyClass::staticVar = 5;
MyClass::printStaticVar(); // 5
return 0;
}
4.静态成员函数
在类中使用 static
关键字声明的函数是静态成员函数。静态成员函数可以访问静态成员变量,但不能访问非静态成员变量或函数。它们不依赖于类的实例,可以直接通过类名调用。
#include <iostream>
class MyClass {
public:
static void staticFunction() {
std::cout << "Static function called" << std::endl;
}
};
int main() {
MyClass::staticFunction(); // Static function called
return 0;
}
5. 静态函数(文件作用域)
在文件作用域使用 static
关键字声明的函数只能在声明它的文件中可见(具有内部链接),其他文件无法调用。
// file1.cpp
static void printMessage() {
std::cout << "Hello, World!" << std::endl;
}
// file2.cpp
extern void printMessage();
int main() {
printMessage(); // 错误:无法解析外部符号 printMessage
return 0;
}