¿Coloco el resultado de malloc?

En esta pregunta, alguien sugirió en un comentario que debería no lanzar el resultado de malloc, es decir

int *sieve = malloc(sizeof(int) * length);

en lugar de:

int *sieve = (int *) malloc(sizeof(int) * length);

¿Por qué sería este el caso?

Solución

No; usted no arroja el resultado, ya que:

  • Es innecesario, ya que void * es automáticamente y con seguridad promovido a cualquier otro tipo de puntero en este caso.
  • Añade desorden al código, los lanzamientos no son muy fáciles de leer (especialmente si el tipo de puntero es largo).
  • Hace que te repitas, lo que generalmente es malo.
  • Puede ocultar un error si olvidaste incluir `. Esto puede causar fallos (o, peor aún, *no* causar un fallo hasta mucho más tarde en alguna parte totalmente diferente del código). Considere lo que ocurre si los punteros y los enteros tienen tamaños diferentes; entonces está ocultando una advertencia mediante un casting y podría perder bits de su dirección devuelta. Nota: a partir de C99 las funciones implícitas han desaparecido de C, y este punto ya no es relevante ya que no se asume automáticamente que las funciones no declaradas devuelvanint`.

Como aclaración, nótese que he dicho "no hay que hacer castings", no "no hay que hacer castings". En mi opinión, es un fallo incluir el casting, incluso si lo haces bien. Sencillamente no hay beneficios en hacerlo, sino un montón de riesgos potenciales, e incluir el yeso indica que no conoces los riesgos.

También hay que tener en cuenta, como señalan los comentaristas, que lo anterior habla de C directo, no de C++. Creo firmemente en C y C++ como lenguajes separados.

Para añadir algo más, tu código repite innecesariamente la información de tipo (int) lo que puede causar errores. Es mejor desreferenciar el puntero que se utiliza para almacenar el valor de retorno, para "bloquear" los dos juntos:

int *sieve = malloc(length * sizeof *sieve);

Esto también mueve la "longitud" al frente para una mayor visibilidad, y elimina los paréntesis redundantes con "sizeof"; sólo son necesarios cuando el argumento es un nombre de tipo. Mucha gente parece no saber (o ignorar) esto, lo que hace que su código sea más verboso. ¡Recuerde: sizeof no es una función! :)


Mientras que mover length al frente puede aumentar la visibilidad en algunos casos raros, también hay que prestar atención a que en el caso general, debería ser mejor escribir la expresión como:

int *sieve = malloc(sizeof *sieve * length);

Ya que mantener el sizeof primero, en este caso, asegura que la multiplicación se hace con al menos size_t matemático.

Compara: malloc(sizeof *sieve * length * width) frente a malloc(length * width * sizeof *sieve) el segundo puede desbordar el length * width cuando width y length son tipos menores que size_t.

Comentarios (32)

En C, no es necesario convertir el valor de retorno de malloc. El puntero a void devuelto por malloc se convierte automáticamente al tipo correcto. Sin embargo, si quieres que tu código compile con un compilador de C++, es necesario hacer un casting. Una alternativa preferida entre la comunidad es utilizar lo siguiente:

int *sieve = malloc(sizeof *sieve * length);

que además te libera de tener que preocuparte de cambiar el lado derecho de la expresión si alguna vez cambias el tipo de sieve.

Los lanzamientos son malos, como la gente ha señalado. Especialmente los lanzamientos de punteros.

Comentarios (8)

En C se obtiene una conversión implícita de void* a cualquier otro puntero (de datos).

Comentarios (2)