C语言 动态内存分配

C语言 动态内存分配

参考:

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 语言中如何进行动态内存分配


主要内容:

  1. sizeofstrlen
  2. free
  3. memset
  4. malloccallocrealloc

sizeofstrlen

在分配内存之前,需要了解给指针分配多少个字节的内存块,使用函数 sizeof 和 strlen

sizeof

百度百科:sizeof

sizeofC/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;
}

结果:

C语言 动态内存分配_第1张图片

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;
}

结果:

C语言 动态内存分配_第2张图片

利用 sizeofstrlen 进行指针的内存分配

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);

功能:释放动态申请的内存块

指针在进行动态内存分配时,是从堆上获取,这意味着申请的内存并不会随着函数的结束而自动释放,会造成内存泄漏,所以需要手动释放内存空间

常用的动态内存分配函数有 malloccallocrealloc,所以使用上述三种函数获取的内存空间在使用结束后需要手动调用 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:如果申请的内存马上要被覆盖,没必要进行清零操作


malloccallocrealloc

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

callocmalloc 的函数功能相近,只是多了一步初始化清零的操作

代码如下:

#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);

以防内存申请失败,函数返回空时,无法找到原先的内存地址

你可能感兴趣的:(c)