"C trampas y defectos"----Capítulo 5 Funciones de biblioteca

5.1 La función getchar que devuelve un número entero

Código:

#include<stdio.h>
int main()
{
	char c;
	while((c = getchar())!=EOF)//getchar函数的返回值为整型
		putchar(c);
	return 0;
}

Hay tres posibilidades para el código anterior:

  1. Algunos caracteres de entrada válidos se "truncan" para que c tenga el mismo valor que EOF, y el programa se detendrá a la mitad de la copia.
  2. Es imposible que c obtenga el valor de EOF y cae en un bucle infinito.
  3. El programa aparentemente funciona, pero es pura coincidencia. Aunque el resultado de retorno de la función geutchar se "truncará" cuando se asigne a la variable c de tipo char, muchos compiladores no comparan c y EOF en la expresión de comparación, pero comparan el valor de retorno de la función getchar con EOF! , si el compilador hubiera adoptado este enfoque, el ejemplo anterior habría funcionado bien.

5.2 Actualizar archivo de secuencia

Cuando use r+ para escribir y leer archivos al mismo tiempo, use fseek para mover el puntero, porque la posición a la que apunta el puntero del archivo cambia mientras escribe y lee.

5.3 Salida almacenada en búfer y asignación de memoria

Hay dos formas de salida del programa: una es el procesamiento inmediato; la otra se almacena temporalmente y luego se escribe en bloques grandes.

setbuf(stdout,buf);

declaración notificará a la biblioteca de entrada/salida. Toda la salida escrita en stdout debe usar buf como el búfer de salida hasta que se llene el búfer buf o el programador llame directamente a fflush (para los archivos abiertos mediante operaciones de escritura, llamar a fflush hará que el contenido del búfer de salida se escriba realmente) en el archivo) , el contenido del búfer buf en realidad se escribe en stdout. El tamaño del búfer lo define BUFSIZ en el archivo de encabezado del sistema <stdio.h>.

Aquí hay un ejemplo:

#include<stdio.h>
int main()
{
	int c;
	char buf[BUFSIZ];
	setbuf(stdout,buf);
	while((c = getchar())!=EOF)
		putchar(c);
}

El programa anterior es incorrecto porque la última vez que se vacía el búfer buf es después de que finaliza la función main(), como parte de la limpieza que debe hacer la biblioteca de tiempo de ejecución de C antes de entregar el control al sistema operativo. Sin embargo, la matriz de caracteres buf se ha liberado antes de eso.

Dos soluciones:

  1. static char buf[BUFSIZ];
    
  2. setbuf(stdout,(char*)malloc(BUFSIZ));
    //此处不需要检查malloc函数调用是否成功,因为setbuf函数的第二个参数取值可以为NULL,此时标准输出不需要进行缓冲。
    

5.5 Funciones de biblioteca

La implementación del lenguaje C incluye la función de biblioteca de señales como una forma de capturar el tiempo asíncrono.

#include<signal.h>//需要引用的头文件
signal(signal type , handler function);

El tipo de señal aquí representa algunas constantes definidas en el archivo de encabezado del sistema signal.h, estas constantes se utilizan para identificar el tipo de señal que capturará la función de señal. La función de controlador aquí es el controlador de eventos que se llamará cuando ocurra el evento especificado.

Nota: Las señales pueden incluso aparecer durante la ejecución de algunas funciones de biblioteca complejas, como malloc. . Por lo tanto, desde el punto de vista de la seguridad, los controladores de señales no deberían llamar a funciones de biblioteca del tipo anterior.

Por ejemplo: Supongamos que la ejecución de la función malloc es interrumpida por una señal. En este punto, es probable que las estructuras de datos que utiliza malloc para realizar un seguimiento de la memoria disponible solo estén parcialmente actualizadas. Si la función de procesamiento de señales vuelve a llamar a la función malloc, el resultado puede ser que la estructura de datos utilizada por la función malloc se colapsa por completo y las consecuencias son inimaginables.

Conclusión: las señales son complejas y engañosas y tienen algunas propiedades inherentes que no son portátiles. Por lo tanto, debemos mantener las funciones que señalan los identificadores lo más simples posible y organizarlas juntas para que podamos modificarlas fácilmente cuando necesitemos adaptarnos a un nuevo sistema.

práctica

  1. P: Cuando un programa finaliza de manera anormal, las últimas líneas de salida del programa a menudo se pierden, ¿por qué? ¿Qué medidas podemos tomar para solucionar este problema?

    R: Es posible que un programa que finaliza de manera anormal no tenga la oportunidad de vaciar sus búferes de salida, por lo que la salida generada por el programa puede estar en algún lugar de la memoria pero nunca se puede escribir. En algunos sistemas, los datos de salida que no se pueden escribir pueden tener varias páginas.

    Para los programadores que depuran dichos programas, esta pérdida de resultados a menudo es engañosa, ya que crea la impresión de que el momento en que el programa falla es mucho antes de lo que realmente falla. **La solución es forzar que la salida no se almacene en búfer durante la depuración. **La solución es la siguiente:

    setbuf(stdout,(char*)0);
    

    Esta declaración debe ejecutarse antes de que se escriba cualquier salida en stdout (incluidas las llamadas a la función printf). El lugar más apropiado para esta declaración es como la primera declaración de la función principal.

  2. El propósito del siguiente programa es copiar su entrada a su salida:

    #include<stdio.h>
    int main()
    {
    	register int c;
    	while((c = getchar())!=EOF)
    		putchar(c);
    	return 0;
    }
    

    Cambie el código al siguiente código, el programa aún puede ejecutarse correctamente, pero es mucho más lento, ¿por qué?

    #define EOF -1
    int main()
    {
    	register int c;
    	while((c = getchar())!=EOF)
    		putchar();
    	return 0;
    }
    

    Las llamadas a funciones toman más tiempo de ejecución del programa, por lo que getchar a menudo se implementa como una macro. Esto se define en stdio.h, por lo que un programa que no incluye el archivo de encabezado stdio.h reemplaza la macro getchar con una llamada de función getchar dondequiera que aparezca la macro fgetchar. Este programa es lento debido al aumento de la sobrecarga causado por las llamadas a funciones. El mismo razonamiento se aplica a putchar.

Supongo que te gusta

Origin blog.csdn.net/m0_57304511/article/details/123690989
Recomendado
Clasificación