¿Por qué C++ requiere una conversión para malloc() pero C no?

Resuelto bodacydo asked hace 14 años • 4 respuestas

Siempre he tenido curiosidad acerca de esto: ¿por qué en C++ tengo que convertir el valor de retorno mallocpero no en C?

Aquí está el ejemplo en C++ que funciona:

int *int_ptr = (int *)malloc(sizeof(int*));

Y aquí está el ejemplo en C++ que no funciona (sin conversión):

int *int_ptr = malloc(sizeof(int*));

Escuché que en C, de hecho, emitir una salida malloc()es un error.

¿Alguien puede comentar sobre este tema?

bodacydo avatar Aug 13 '10 21:08 bodacydo
Aceptado

Varios puntos:

C permite convertir implícitamente punteros nulos a cualquier otro tipo de puntero de objeto. C++ no lo hace.

Transmitir el resultado de malloc()en C suprimirá un diagnóstico útil si olvida incluir stdlib.h o no tiene una declaración dentro del malloc()alcance. Recuerde que si C ve una llamada a una función sin una declaración previa, asumirá que la función devuelve int. Si no tiene una declaración malloc()y omite la conversión, obtendrá un diagnóstico en el sentido de que está intentando asignar tipos incompatibles (int a puntero). Si transmite el resultado, suprime el diagnóstico y potencialmente tendrá problemas de tiempo de ejecución, ya que no se garantiza que convertir un valor de puntero a un int y volver a un puntero le proporcione un resultado útil.

Si estás escribiendo C++, deberías usar newy deleteen lugar de malloc()y free(). Sí, sí, sí, he escuchado todas las razones por las que la gente quiere que su código se compile como C y C++, pero los beneficios de usar la herramienta de administración de memoria adecuada para el lenguaje superan el costo de mantener dos versiones en mi opinión.

Nota: el void *tipo fue agregado en la norma C89; Las versiones anteriores de C tenían malloc()return , por lo que en esas versiones sechar * requería la conversión si se asignaba el resultado a un tipo de puntero diferente. Sin embargo, casi todo el mundo admite al menos el estándar C89, por lo que las probabilidades de que te encuentres con una de esas implementaciones más antiguas son muy, muy bajas.

John Bode avatar Aug 13 '2010 14:08 John Bode

Esto se debe a que C++ es un lenguaje fuertemente tipado. En C++, las conversiones implícitas sólo se permiten si se están "ampliando", es decir, si el nuevo tipo puede contener todos los valores que el tipo anterior puede contener. Se permite la conversión de un tipo entero más pequeño a un tipo entero más grande; void*se permite la conversión desde cualquier tipo de puntero a ; Se permite la conversión de una subclase a su superclase. Todas las demás conversiones deben realizarse explícitamente, diciéndole así al compilador "Sé lo que estoy haciendo, esto no es un error".

malloc()devuelve a void*, que podría ser cualquier cosa, por lo que el compilador no puede garantizar que su conversión tenga éxito (o sea significativa). Al utilizar una conversión explícita, le estás diciendo al compilador que lo que estás haciendo es realmente intencional.

C, OTOH, no tiene reglas de casting tan rígidas; usted puede elegir entre dos tipos cualesquiera y usted, como programador, es responsable de asegurarse de que no sucedan cosas malas como consecuencia.

tdammers avatar Aug 13 '2010 14:08 tdammers

C admite la conversión implícita desde void*otros tipos de punteros. C++ no lo permite.

Una razón por la que en C está mal visto emitir explícitamente el valor de retorno malloces que si la mallocfirma no está incluida en la unidad de compilación actual, el compilador asumirá que el tipo de retorno es inty la conversión implícita al tipo de puntero que está la asignación da como resultado una advertencia en tiempo de compilación que resolvería inmediatamente. Con una conversión explícita, si cometes este error, no se emitirá ninguna advertencia.

Mehrdad Afshari avatar Aug 13 '2010 14:08 Mehrdad Afshari