Mi informacion de contacto
Correo[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
1. Situación básica
La gestión de la memoria del lenguaje C se divide en dos partes: gestión del sistema y gestión del manual de usuario del programador. La memoria administrada por el sistema son principalmente las variables (variables locales) dentro de la función. Esta parte de las variables ingresa a la memoria cuando la función se está ejecutando. Esta parte del área de memoria se convierte en el "área de pila". , el sistema operativo lo descarga automáticamente de la memoria. La memoria administrada manualmente por el usuario son principalmente variables (variables globales) que existen durante todo el proceso de ejecución del programa. El área de memoria donde se encuentra esta parte se llama "área del montón". Estas variables deben liberarse manualmente de la memoria. por el usuario. Si olvida liberarlo después de su uso, seguirá ocupando memoria hasta que se entregue al sistema operativo cuando se cierre el programa.
2. puntero vacío
Al espacio de memoria en la computadora se le asigna un código de dirección único y el área de memoria especificada se puede encontrar a través del puntero de memoria. Las variables de puntero deben tener un tipo, por ejemplo: int* p=&x; declara un puntero de tipo int, que apunta a la dirección de la variable entera x. Cuando el compilador obtiene los datos de esta dirección, sabe que el tipo int. se almacenan los datos. Cuando no está seguro de qué tipo de datos se almacenan y solo desea encontrar primero la dirección de la memoria del bloque, se utiliza el puntero de tipo vacío. Un puntero de tipo vacío también se denomina puntero de tipo indefinido y puede apuntar a cualquier tipo de datos.
Los punteros de tipo void se pueden convertir en punteros de otros tipos y su uso no tiene nada de especial, excepto que el contenido almacenado no se puede analizar mediante el método "*".
int x = 10; //Declarar variable entera x
void* p = &x; // Declara el puntero nulo y apunta a la dirección de x, lo que indica que el puntero int (&x) se convierte en un puntero nulo.
int* q = p; // el puntero vacío se convierte nuevamente en un puntero entero
printf( "%in", *q ); //Resultado de la ejecución: 10
Preste atención a la diferencia entre void* y void: void no tiene tipo y cuando se usa para declarar una función, significa que no hay valor de retorno, mientras que void*, aunque no tiene tipo pero tiene un puntero, devuelve algo;
3. Funciones relacionadas con la gestión de la memoria.
1、malloc()
Esta función se puede recordar por separado. m es la abreviatura de memoria y alloc es la abreviatura de asignación. Juntos asignan memoria.
Función: solicitar un bloque de memoria continuo del área del montón (recordatorio: la memoria del área del montón debe ser administrada por el programador y debe destruirse después de su uso. Esto siempre debe recordarse en el formato de uso: malloc (consulte 1);
Parámetros: el parámetro 1 es el tamaño del bloque de memoria (un entero no negativo de tipo size_t, el valor de retorno de sizeof es de este tipo)
Valor de retorno: puntero void* (usaremos cualquier tipo de puntero que usemos para recibir la memoria asignada)
Uso: Las variables declaradas usando la función malloc están en el área del montón, por lo que a menudo se usa el método de declaración anónima, es decir, en lugar de usar el método de dirección de variables específicas, malloc devuelve directamente el puntero, como se muestra a continuación:
int* ptr = (int*) malloc(sizeof(int)); //Se declara una variable de puntero int en el área del montón
La conversión forzada entre paréntesis no es necesaria. malloc devuelve void*, que se puede recibir con int*. La conversión fuerte aquí hace que el código sea más fácil de entender.
Precauciones:
a. Utilice la función malloc para incluir.<stdlib.h>archivo de encabezado, como solo contiene<stdio.h> Se compila bien pero no se ejecuta correctamente, téngalo en cuenta.
b. Asigne valor a ptr: *ptr=1000;.
c. Utilice malloc junto con free (que encontrará más adelante). No olvide free (ptr);
d. Es posible que Malloc no tenga éxito en la asignación de direcciones. Si no tiene éxito, devolverá NULL. Por este motivo, se puede agregar una declaración if para su procesamiento.
e. malloc solo asigna memoria, independientemente de la inicialización. Si se requiere inicialización, se debe llamar a otra función.
f. La ocasión más utilizada para malloc es asignar memoria para matrices y estructuras de datos personalizadas.
2、memset()
Función: Asigne un valor inicial a cada byte en el bloque de memoria al que apunta un puntero.
Parámetros: Parámetro 1 Puntero que apunta a la memoria de destino Parámetro 2 Contenido de la asignación (valor de código ASCII de tipo int o carácter de tipo char) Parámetro 3 Número de bytes a asignar (tipo size_t)
Valor de retorno: devuelve el puntero apuntado a la memoria de destino. No tiene sentido recibirlo, al igual que el parámetro 1.
Uso: memset(ptrDestMem,'A',sizeof(char)*1024) //Asigna el carácter A a cada byte de un bloque de memoria con una longitud de 1024 bytes
Precauciones:
a. El archivo de encabezado al que pertenece esta función es.<string.h> , algunos compiladores se pueden utilizar normalmente sin incluir este archivo de encabezado. Si se produce un error de ejecución, inclúyalo.
b. Tenga en cuenta que memset es una operación en bytes (no en bits); el parámetro 3 se refiere a cuántos bytes deben asignarse, que puede ser menor o igual que el número de bytes en la memoria de destino, pero no puede exceder el límite.
c. El valor del parámetro 2 no puede exceder lo que puede acomodar un byte (tipo int 255). Si excede el valor, no se puede escribir.
2、gratis()
Función: función emparejada con malloc, utilizada para liberar la memoria asignada por la función malloc y evitar pérdidas de memoria
Parámetros: puntero devuelto por la función malloc
Uso: gratis(ptr);
Precauciones:
a. Los archivos de encabezado que deben incluirse cuando se usa gratis también lo son.<stdlib.h> , no lo olvides.
b. La función libre solo se puede ejecutar una vez, la misma dirección de memoria no se puede liberar repetidamente y el puntero liberado no se puede volver a utilizar.
c. Es mejor escribir malloc y free en pares primero y luego insertar otros códigos en el medio para evitar olvidos.
3. reasignar()
re, que significa nuevamente, abreviatura de asignación alloc, juntos significa reasignación de memoria
Función: Modificar el tamaño del bloque de memoria asignado (aumentar o disminuir).
Parámetros: parámetro 1, puntero del bloque de memoria original, parámetro 2, tamaño del bloque de memoria después de aumentar o disminuir (aún tipo size_t)
Valor de retorno: puntero void* (puede ser recibido por la variable de tipo de puntero original)
Uso: void* newPtr=realloc(ptr,sizeof(int)*10);
Precauciones:
a Cuando se utiliza la función de reasignación, también es necesario incluirla.<stdlib.h> .
b El bloque de memoria al que apunta el puntero original ha sido reemplazado por el nuevo puntero, por lo que es el nuevo puntero el que debe liberarse cuando finaliza el programa y no es necesario liberar el puntero original; de lo contrario, se producirá un error de operación. ocurrir.
c. Realloc puede fallar al asignar memoria y devolver NULL si falla, por lo que es mejor agregar una declaración if para solucionarlo.
4. Ejemplos de aplicación
- #include<stdio.h>
- #include<stdlib.h> //malloc、free、realloc
- #include<string.h> //memset
- int main(void)
- {
- //A void指针的使用
- float PI = 3.14159;
- void* pPI = &PI;
- float r = 2.5;
- printf("半径2.5圆的面积:%fn", r * r * *(float*)pPI);//*(float*)pPI—pPI强转为float指针后再解出指向的值
- //B malloc、memset、free函数使用
- int n = 8;
- void* pMyMem = malloc(sizeof(char)*n); //char占1字节,malloc分派n字节的内存,返给void指针
- if (pMyMem == NULL)return 0; //若分派内存失败,程序结束
- void* myMem2=memset(pMyMem,'B',sizeof(char)*8); //对malloc分派的内存区块个字节都写入字符'B'。
- //并用myMem2接收返回的指针
- if (pMyMem == myMem2)printf("memset写入区块指针与其返回的指针相同n");
- char* transCh = pMyMem; //将void指针转成char型指针
- printf("显示写入内容:");
- for (int i = 0; i < n; i++)
- {
- printf("%c ", *transCh); //显示写入的字符
- transCh++;
- }
- printf("n");//换行
- free(pMyMem); //释放malloc函数分派的内存
- //free(ch); //只有malloc分派的内存才需要释放,且只释放一次(这里会报错)
- //C realloc、free函数的使用
- int* pMem = malloc(sizeof(int)*5);
- if (pMem == NULL)return 0;
- for (int i = 0; i < 5; i++) pMem[i] = (i+1)*10;
- for (int i = 0; i < 5; i++) printf("%i ", pMem[i]);
- printf("n重新增加分派内存后n");
- int* newpMem = realloc(pMem, sizeof(int) * 10);
- if (newpMem == NULL)return 0;
- for (int i = 0; i < 10; i++) newpMem[i] = (i + 1) * 10;
- for (int i = 0; i < 10; i++)printf("%i ", newpMem[i]);
- free(newpMem); //释放realloc的内存
- //free(pMem);//pMem已被重置,不能再释放,此语句会造成运行失败
- getchar(); //暂停屏幕
- return 0;
- }