参考:
Sizeof与Strlen的区别与联系:http://blog.csdn.net/u012005313/article/details/46790921
C/C++ memset的作用以及memcpy和strcpy的区别:http://blog.csdn.net/u012005313/article/details/48005689
Linux C语言应用 - main函数解析,时间函数,C语言代码的分配机制(malloc,calloc,realloc,free):http://blog.csdn.net/u012005313/article/details/50704866
关于如何在 C
语言中进行动态内存分配,之前也有过一些总结,不过并没有深入。在查找的过程中,发现很多知识忘记了,所以记录下这篇关于 C
语言中如何进行动态内存分配
主要内容:
sizeof
和 strlen
free
memset
malloc
、calloc
、realloc
sizeof
和 strlen
在分配内存之前,需要了解给指针分配多少个字节的内存块,使用函数 sizeof
和 strlen
:
sizeof
百度百科:sizeof
sizeof
是 C/C++
中的一个操作符,其作用是返回一个对象或类型所占的内存字节数
其返回值类型为 size_t
,通常是 unsigned int
当参数为指针时,其返回值为存储该指针所占的空间大小(即存储该指针的地址的长度)
当参数为数组时,其返回值为分配的数组空间大小
程序如下:
#include
#include
#include
int main(int argc, char* argv[]) {
char arr[200] = "Hello World";
printf("sizeof(arr): %d\n", sizeof(arr));
printf("arr: %s\n", arr);
char *brr = "Hello World";
printf("sizeof(brr): %d\n", sizeof(brr));
printf("brr: %s\n", brr);
char *crr = NULL;
printf("sizeof(crr): %d\n", sizeof(crr));
printf("crr: %s\n", crr);
crr = (char*)malloc(sizeof(arr));
strcpy(crr, arr);
printf("sizeof(crr): %d\n", sizeof(crr));
printf("crr: %s\n", crr);
free(crr);
system("pause");
return 0;
}
结果:
strlen
百度百科:strlen
strlen
函数的功能是返回字符串的长度(遇到第一个结束符 \0
为止,但不包括 \0
)
其返回值为 size_t
,通常为 unsigned int
程序如下:
#include
#include
#include
int main(int argc, char* argv[]) {
char arr[200] = "Hello World";
printf("sizeof(arr): %d\n", sizeof(arr));
printf("strlen(arr): %d\n", strlen(arr));
printf("arr: %s\n", arr);
char *brr = "Hello World";
printf("sizeof(brr): %d\n", sizeof(brr));
printf("strlen(brr): %d\n", strlen(brr));
printf("brr: %s\n", brr);
char *crr = NULL;
printf("sizeof(crr): %d\n", sizeof(crr));
//printf("strlen(crr): %d\n", strlen(crr));
printf("crr: %s\n", crr);
crr = (char*)malloc(sizeof(arr));
strcpy(crr, arr);
printf("sizeof(crr): %d\n", sizeof(crr));
printf("strlen(crr): %d\n", strlen(crr));
printf("crr: %s\n", crr);
free(crr);
system("pause");
return 0;
}
结果:
sizeof
和 strlen
进行指针的内存分配在 C
语言中,字符串/字符数组以 \0
结尾;同时输出字符串/字符数组时并不会输出 \0
所以在动态申请内存时,需要注意申请到 \0
的内存空间
程序 1
功能:复制单个字符串
代码如下:
#include
#include
#include
int main(int argc, char* argv[]) {
char str[30] = "Hello World";
printf("str: %s\n", str);
char* ptr = NULL;
ptr = (char*)malloc(strlen(str) * sizeof(char) + 1);
strcpy(ptr, str);
printf("ptr: %s\n", ptr);
free(ptr);
system("pause");
return 0;
}
结果:
程序 2
功能:复制多个字符串
代码如下:
#include
#include
#include
int main(int argc, char* argv[]) {
char str[30] = "Hello World";
printf("str: %s\n", str);
char* ptr1 = "1234 asdf 5678";
printf("ptr1: %s\n", ptr1);
int len = strlen(str) + strlen(ptr1);
char* ptr2 = NULL;
ptr2 = (char*)malloc(len * sizeof(char) + 1);
sprintf(ptr2, "%s%s", str, ptr1);
printf("ptr2: %s\n", ptr2);
free(ptr2);
system("pause");
return 0;
}
结果:
note:在进行动态内存分配过程中,先计算出要分配的字符个数,再结合单个字符的长度,同时加上 \0
的长度(加上 1
),进行动态内存分配
free
百度百科:free
cstdlib:free
函数:
void free (void* ptr);
功能:释放动态申请的内存块
指针在进行动态内存分配时,是从堆上获取,这意味着申请的内存并不会随着函数的结束而自动释放,会造成内存泄漏,所以需要手动释放内存空间
常用的动态内存分配函数有 malloc
、calloc
、realloc
,所以使用上述三种函数获取的内存空间在使用结束后需要手动调用 free
进行释放
note1:free
完指针后最好手动将指针置为 NULL
(如果指针为空,则调用多少次 free
都不会出现问题;但如果不为空,则连续操作两次就会导致程序异常)
memset
百度百科:memset
函数:
void *memset(void *s, int ch, size_t n);
s
为指向的内存首地址;ch
为要赋值所指定的值;n
为要操作的字节数其返回值为指向 s
的指针
功能:对内存块进行统一赋值操作,通常用来为新申请的内存进行初始化工作,设为 0
即可,例如:
memset(s, 0, strlen(s) * sizeof(s))
note:如果申请的内存马上要被覆盖,没必要进行清零操作
malloc
、calloc
、realloc
malloc
百度百科:malloc
函数:
extern void *malloc(unsigned int num_bytes);
功能:向系统申请分配 num_bytes
个字节的内存空间,该内存空间并未进行初始化
返回为 void*
类型,可通过类型转换得到需要类型的指针
代码如下:
#include
#include
#include
int main(int argc, char* argv[]) {
char* ptr = (char*)malloc(sizeof(char) * 30);
printf("ptr: %s\n", ptr);
memset(ptr, 0, sizeof(char) * 30);
printf("ptr: %s\n", ptr);
strcpy(ptr, "Hello World");
printf("ptr: %s\n", ptr);
free(ptr);
system("pause");
return 0;
}
结果:
calloc
百度百科:calloc
函数:
void *calloc(size_t n, size_t size);
功能:申请 n
个长度为 size
字节的连续空间,并自动初始化该内存空间为 0
calloc
和 malloc
的函数功能相近,只是多了一步初始化清零的操作
代码如下:
#include
#include
#include
int main(int argc, char* argv[]) {
//char* ptr = (char*)malloc(sizeof(char) * 30);
char* ptr = (char*)calloc(30, sizeof(char));
printf("ptr: %s\n", ptr);
//memset(ptr, 0, sizeof(char) * 30);
//printf("ptr: %s\n", ptr);
strcpy(ptr, "Hello World");
printf("ptr: %s\n", ptr);
free(ptr);
system("pause");
return 0;
}
结果:
realloc
百度百科:realloc
cstdlib:realloc
函数:
extern void *realloc(void *mem_address, unsigned int newsize);
功能:
mem_address
所知内存空间后面还有足够空间,则扩大 mem_address
所指内存空间;newsize
小于原先的内存块大小,则有可能会导致数据丢失函数运行成功则返回指向被分配内存的指针,否则返回空指针 NULL
(返回 NULL
时,指针 mem_address
所指内容依旧存在)
经典案例如下:
/* realloc example: rememb-o-matic */
#include /* printf, scanf, puts */
#include /* realloc, free, exit, NULL */
int main()
{
int input, n;
int count = 0;
int* numbers = NULL;
int* more_numbers = NULL;
do {
printf("Enter an integer value (0 to end): ");
scanf("%d", &input);
count++;
more_numbers = (int*)realloc(numbers, count * sizeof(int));
if (more_numbers != NULL) {
numbers = more_numbers;
numbers[count - 1] = input;
}
else {
free(numbers);
puts("Error (re)allocating memory");
exit(1);
}
} while (input != 0);
printf("Numbers entered: ");
for (n = 0; n
我写了一个例子:
#include
#include
#include
int main(int argc, char* argv[]) {
char str[200] = "Hello World";
char str2[200] = "adf 134 adeca adfadec";
char* ptr = NULL;
ptr = (char*)malloc(strlen(str) * sizeof(str) + 1);
strcpy(ptr, str);
printf("ptr: %s\n", ptr);
int len = strlen(str) + strlen(str2);
char* temp = NULL;
temp = (char*)realloc(ptr, len * sizeof(char) + 1);
if (temp) {
ptr = temp;
strcat(ptr, str2);
printf("ptr: %s\n", ptr);
}
free(ptr);
system("pause");
return 0;
}
结果:
note1:函数 realloc
中的参数指针和返回指针不要使用同一个,例如:
temp = (char*)realloc(temp, 100);
以防内存申请失败,函数返回空时,无法找到原先的内存地址