Pergunta

Na esta questão , alguém sugeriu em um comentário que eu deve não converter o resultado de malloc, ou seja

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

em vez de:

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

Por que isso seria o caso?

Foi útil?

Solução

Não ; você não converter o resultado, uma vez que:

  • É desnecessário, como void * é automaticamente e com segurança promovido a qualquer outro tipo de ponteiro neste caso.
  • Acrescenta desordem para o código, moldes não são muito fáceis de ler (especialmente se o tipo de ponteiro é longa).
  • Isso faz você repetir-se, que geralmente é ruim.
  • Pode esconder um erro se você se esqueceu de incluir <stdlib.h>. Isso pode causar falhas (ou, pior, não causar um acidente até meio depois, em alguma parte totalmente diferente do código). Considere o que acontece se os ponteiros e inteiros são de tamanhos diferentes; então você está escondendo um aviso por vazamento e pode perder pedaços de seu endereço retornado. Nota:. A partir de funções implícitas C11 são idos de C, e este ponto não é relevante uma vez que não há nenhuma suposição automática de que as funções não declaradas retornar int

Como um esclarecimento, nota que eu disse "você não lançar", não "você não necessidade para elenco". Na minha opinião, é um fracasso para incluir o elenco, mesmo se você acertou. Simplesmente não existem benefícios para fazê-lo, mas um monte de riscos potenciais, incluindo o elenco indica que você não sabe sobre os riscos.

Além disso, observe como os comentadores salientar, que as negociações acima sobre C em linha reta, não C ++. Eu acredito muito firmemente em C e C ++ como línguas separadas.

Para adicionar ainda mais, o seu código desnecessariamente repete as informações de tipo (int), que pode causar erros. É melhor cancelar o ponteiro sendo usada para armazenar o valor de retorno, de "bloqueio" os dois juntos:

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

Isso também move o length para a frente para maior visibilidade, e deixa cair os parênteses redundantes com sizeof; eles só são necessários quando o argumento é um nome de tipo. Muitas pessoas parecem não saber (ou ignorar) esse, o que torna seu código mais detalhado. Lembre-se: sizeof não é uma função! :)


Enquanto se move length para a frente pode aumentar a visibilidade em alguns casos raros, um também deve prestar atenção que, no caso geral, deve ser melhor para escrever a expressão como:

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

Uma vez que manter o sizeof primeiro, neste caso, garante a multiplicação é feita com pelo menos matemática size_t.

Compare:. malloc(sizeof *sieve * length * width) vs. malloc(length * width * sizeof *sieve) o segundo pode transbordar o length * width quando width e length são tipos menores do que size_t

Outras dicas

Em C, você não precisa converter o valor de retorno de malloc. O ponteiro para vazio retornado por malloc é automágicamente convertido para o tipo correcto. No entanto, se você quer que seu código para compilar com o compilador C ++, é necessário um elenco. A alternativa preferida entre a comunidade é usar o seguinte:

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

que, adicionalmente, liberta-o de ter que se preocupar sobre como alterar o lado direito da expressão, se alguma vez você alterar o tipo de sieve.

moldes são ruins, como as pessoas têm apontado. Especialmente pointer cast.

Você do elenco, porque:

  • Não faz o seu código de mais portáteis entre C e C ++, e como assim que a experiência mostra, um grande número de programadores afirmam que eles estão escrevendo em C quando eles estão realmente escrevendo em C ++ (ou C mais compilador locais extensões).
  • Caso não o faça pode esconder um erro :. Nota todos os exemplos de SO de confundir quando type * escrita contra type **
  • A ideia de que o impede de perceber que você não conseguiu #include um erra arquivo de cabeçalho apropriadas a floresta para as árvores . É o mesmo que dizer "não se preocupe com o fato de você não conseguiu pedir o compilador para reclamar sobre não ver protótipos - que stdlib.h traquinas é a coisa mais importante real para se lembrar"
  • Obriga um adicional cognitiva verificação cruzada . Ele coloca o (alegado) tipo desejado ao lado da aritmética que você está fazendo para o tamanho cru dessa variável. Eu aposto que você poderia fazer um estudo para que mostra que erros malloc() são capturados muito mais rápido quando há um elenco. Tal como acontece com as afirmações, anotações que revelam erros diminuição intenção.
  • Repetindo-se de uma forma que a máquina pode verificar é muitas vezes um grande idéia. Na verdade, isso é o que uma afirmação é, e este uso do elenco é uma afirmação. Afirmações ainda são a técnica geral mais que temos para obter o código correto, já que Turing veio com a idéia de tantos anos atrás.

Como outros declarou, não é necessário para C, mas para C ++. Se você acha que está indo para compilar o código C com um compilador C ++, para as quais razões nunca, você pode usar uma macro em vez disso, como:

#ifdef __cplusplus
# define NEW(type, count) ((type *)calloc(count, sizeof(type)))
#else
# define NEW(type, count) (calloc(count, sizeof(type)))
#endif

Dessa forma, você ainda pode escrevê-lo de uma forma muito compacta:

int *sieve = NEW(int, 1);

e ele irá compilar para C e C ++.

A partir da Wikipedia :

Vantagens para lançar

  • Incluindo o fundido pode permitir que um programa ou função C para compilar como C ++.

  • O elenco permite a pré-1989 versões do malloc que originalmente retornou um char *.

  • Fundição pode ajudar o desenvolvedor identificar inconsistências no tipo de dimensionamento deve a mudança de tipo de ponteiro destino, especialmente se o ponteiro é declarado longe da chamada malloc () (embora compiladores modernos e analisadores estáticos pode avisar sobre tal comportamento sem exigir o elenco).

Desvantagens de vazamento

  • De acordo com a norma ANSI C, o molde é redundante.

  • Adicionando o elenco pode mascarar o fracasso para incluir o cabeçalho stdlib.h , em que é encontrado o protótipo para malloc. Na ausência de um protótipo para malloc, a norma exige que o compilador C assume retorna malloc um int. Se não houver um elenco, um aviso é emitido quando este número inteiro é atribuído ao ponteiro; no entanto, com o elenco, este aviso não é produzido, escondendo um bug. em certa arquitecturas e dados modelos (tais como LP64 em sistemas de 64-bit, onde longa e ponteiros são 64 bits e int é de 32-bit), isso pode erro realmente resultar em um comportamento indefinido, como o declarou implicitamente malloc retorna um valor de 32 bits enquanto que a função realmente definida retorna um valor de 64 bits. Dependendo chamando convenções e memória layout, isso pode resultar em pilha estrondoso. Esta questão é menos provável para passar despercebida em compiladores modernos, como eles uniformemente produzir advertências de que uma função não declarado foi usado, então um aviso será ainda aparecem. Por exemplo, o comportamento padrão do GCC é mostrar um aviso "declaração implícita incompatível do built-in função", independentemente do elenco está presente ou não.

  • Se o tipo do ponteiro é alterado a sua declaração, pode-se também, necessidade de mudar todas as linhas onde malloc é chamado e elenco.

Embora malloc sem fundição é o método preferido e mais programadores experientes escolhê-lo , você deve usar o que você gosta de ter conhecimento das questões.

ou seja: Se você precisa compilar programa C como C ++ (embora sejam língua separada) você deve usar malloc com vazamento.

Em C você pode converter implicitamente um ponteiro nulo para qualquer outro tipo de ponteiro, então um elenco não é necessário. Usando um pode sugerir para o observador casual que há alguma razão para que um é necessário, o que pode ser enganosa.

Você não converter o resultado de malloc, pois isso acrescenta a desordem inútil ao seu código.

A razão mais comum pela qual as pessoas converter o resultado de malloc é porque eles não tem certeza sobre como a linguagem C funciona. Isso é um sinal de alerta: se você não sabe como uma determinada obras mecanismo de linguagem, então não ter um palpite. Procurá-lo ou pedir no Stack Overflow.

Alguns comentários:

  • Um ponteiro nulo pode ser convertido para / a partir de qualquer outro tipo de ponteiro sem uma conversão explícita (C11 6.3.2.3 e 6.5.16.1).

  • C ++ irá, contudo, não permitem uma conversão implícita entre void* e outro tipo de ponteiro. Assim, em C ++, o elenco teria sido correto. Mas se você programar em C ++, você deve usar new e não malloc (). E você deve código nunca compilação C usando um compilador C ++.

    Se você precisa para suportar tanto C e C ++ com o mesmo código-fonte, o uso do compilador muda para marcar as diferenças. Não tente saciar ambos os padrões de linguagem com o mesmo código, porque eles não são compatíveis.

  • Se um compilador C não consegue encontrar uma função, porque você se esqueceu de incluir o cabeçalho, você receberá um erro do compilador / vinculador sobre isso. Então, se você se esqueceu de incluir <stdlib.h> isso é nada demais, você não será capaz de construir o seu programa.

  • Em compiladores antigos que seguem uma versão do padrão que é mais de 25 anos de idade, se esquecendo de incluir <stdlib.h> iria resultar em um comportamento perigoso. Porque naquele antigo padrão, funciona sem um protótipo visível convertido implicitamente o tipo de retorno para int. Na conversão do resultado de malloc explicitamente, então, esconder esse bug.

    Mas isso é realmente um não-problema. Você não está usando um computador velho de 25 anos, então por que você usar um compilador de 25 anos de idade?

Em C você começa uma conversão implícita de void* a qualquer outro ponteiro (dados).

Fundição o valor retornado pelo malloc() não é necessário agora, mas eu gostaria de adicionar um ponto que parece que ninguém apontou:

Nos dias antigos, isto é, antes de ANSI C fornece a void * como o tipo genérico de ponteiros, char * é o tipo para essa utilização. Nesse caso, o elenco pode desligar os avisos do compilador.

Referência: C FAQ

Não é obrigatório para lançar os resultados de malloc, uma vez que retorna void*, e uma void* pode ser apontado para qualquer tipo de dados.

Basta adicionar minha experiência, estudando engenharia da computação, vejo que os dois ou três professores que eu já vi escrito em C malloc sempre fundido, no entanto o que eu pedi (com um imenso CV e compreensão de C) me disse que é absolutamente desnecessário, mas utilizado para ser absolutamente específico, e para obter os alunos a mentalidade de ser absolutamente específico. Essencialmente vazamento não vai mudar nada na forma como ele funciona, ele faz exatamente o que diz, aloca memória e fundição não afeta-lo, você recebe a mesma memória, e mesmo se você lançá-lo para outra coisa por engano (e de alguma forma fugir compilador erros) C vai acessá-lo da mesma forma.

Editar: Fundição tem um certo ponto. Quando você usa a notação de matriz, o código gerado tem que saber quantos lugares de memória que tem de antecedência para chegar ao início do próximo elemento, isto é conseguido através de casting. Desta forma, você sabe que por um duplo você vai 8 bytes à frente, enquanto para um int você vá 4, e assim por diante. Assim, não tem efeito se você usar a notação de ponteiro, em ordem de notação torna-se necessário.

Isto é o que O GNU C Library Reference manual diz:

Você pode armazenar o resultado de malloc em qualquer variável ponteiro sem fundido, porque ISO C converte automaticamente o tipo void * para outra tipo de ponteiro quando necessário. Mas o elenco é necessária em contextos diferente de operadores de atribuição ou se você pode querer o seu código seja executado no tradicional C.

E de fato o ISO C11 padrão (P347) diz assim:

O ponteiro retornado se a atribuição sucede é adequadamente alinhadas de modo que pode ser atribuído a um ponteiro para qualquer tipo de objecto com um exigência de alinhamento fundamental e, em seguida, usado para acesso tal objeto ou um array de tais objectos no espaço alocado (até o espaço é explicitamente desalocados)

Um ponteiro nulo é um ponteiro genérico e C suporta a conversão implícita de um tipo de ponteiro void para outros tipos, por isso não há necessidade de typecasting-lo explicitamente.

No entanto, se você quer o mesmo código de trabalho perfeitamente compatível em uma plataforma C ++, que não suporta a conversão implícita, você precisa fazer o typecasting, então tudo depende de usabilidade.

O tipo retornado é void *, que pode ser convertido para o tipo desejado de ponteiro de dados, a fim de ser dereferenceable.

Na linguagem C, um ponteiro nulo pode ser atribuído a qualquer ponteiro, que é por isso que você não deve usar um tipo de elenco. Se você quiser alocação "Tipo de segurança", eu posso recomendar as seguintes funções macro, que eu sempre usar em meus projetos C:

#include <stdlib.h>
#define NEW_ARRAY(ptr, n) (ptr) = malloc((n) * sizeof *(ptr))
#define NEW(ptr) NEW_ARRAY((ptr), 1)

Com estes no lugar que você pode simplesmente dizer

NEW_ARRAY(sieve, length);

Para matrizes não dinâmicos, o terceiro deve ter função de macro é

#define LEN(arr) (sizeof (arr) / sizeof (arr)[0])

que torna variedade laços mais seguro e mais conveniente:

int i, a[100];

for (i = 0; i < LEN(a); i++) {
   ...
}

Depende da linguagem de programação e compilador. Se você usar malloc em C, não há necessidade para o tipo de lançá-lo, como ele irá digitar automaticamente elenco, no entanto, se o seu usando C ++, então você deve digitar elenco porque malloc retornará um tipo void*.

As pessoas costumavam GCC e Clang são mimados. Não é tão bom lá fora.

I foram muito horrorizada ao longo dos anos pelos compiladores incrivelmente idade Eu estive necessários para usar. Muitas vezes as empresas e gestores de adoptar uma abordagem ultra-conservadora para compiladores mudança e não vai mesmo test , se um novo compilador (com o cumprimento melhores padrões e otimização de código) vai trabalhar em seu sistema. A realidade prática para os desenvolvedores trabalhando é que quando você está programando o que você precisa para cobrir suas bases e, infelizmente, lançando mallocs é um bom hábito, se você não pode controlar o compilador pode ser aplicado ao seu código.

Eu também gostaria de sugerir que muitas organizações aplicar um padrão de codificação própria e que que deve ser o método pessoas seguem se estiver definido. Na ausência de orientação explícita I tendem a ir para mais provável para compilar todos os lugares, em vez de aderência servil a um padrão.

O argumento de que não é necessário sob os padrões atuais é bastante válido. Mas esse argumento omite os aspectos práticos do mundo real. Nós não codificam em um mundo governado exclusivamente pelo padrão do dia, mas os aspectos práticos do que eu gosto de chamar de "campo realidade da administração local". E isso é dobrada e torcida tempo mais do que o espaço sempre foi. : -)

YMMV.

Eu tendo a pensar de lançar malloc como uma operação defensiva. Não é bonito, não é perfeito, mas geralmente seguro. (Honestamente, se você não tiver incluído stdlib.h então você tem maneira mais problemas do que lançando malloc!).

Eu coloquei no elenco simplesmente para mostrar a desaprovação do buraco feio no sistema tipo, que permite que o código como o seguinte trecho para compilar sem diagnóstico, mesmo que não moldes são usados ??para trazer a má conversão:

double d;
void *p = &d;
int *q = p;

Eu gostaria que não existia (e isso não acontece em C ++) e assim eu expulso. Ela representa o meu gosto, e minha política de programação. Eu estou não só lançando um ponteiro, mas efetivamente, lançando uma cédula, e os demônios de estupidez . Se eu não puder realmente expulso estupidez , então, pelo menos deixe-me expressar a desejar fazê-lo com um gesto de protesto.

Na verdade, uma boa prática é envolver malloc (e amigos) com funções que retornam unsigned char *, e basicamente nunca usar void * em seu código. Se você precisa de um ponteiro-a-qualquer-objeto genérico, use uma char * ou unsigned char *, e têm elencos em ambas as direções. A um relaxamento que pode ser o espectáculo, talvez, é o uso de funções como memset e memcpy sem moldes.

Sobre o tema da fundição e compatibilidade C ++, se você escrever seu código para que ele compila como C e C ++ (caso em que você Have a converter o valor de retorno de malloc quando atribuí-la a algo diferente de void *), você pode fazer uma coisa muito útil para si mesmo: você pode usar macros para a fundição, que se traduzem em C ++ moldes estilo ao compilar como C ++, mas reduzir ao elenco C ao compilar como C:

/* In a header somewhere */
#ifdef __cplusplus
#define strip_qual(TYPE, EXPR) (const_cast<TYPE>(EXPR))
#define convert(TYPE, EXPR) (static_cast<TYPE>(EXPR))
#define coerce(TYPE, EXPR) (reinterpret_cast<TYPE>(EXPR))
#else
#define strip_qual(TYPE, EXPR) ((TYPE) (EXPR))
#define convert(TYPE, EXPR) ((TYPE) (EXPR))
#define coerce(TYPE, EXPR) ((TYPE) (EXPR))
#endif

Se você aderir a estas macros, então uma busca grep simples de sua base de código para esses identificadores irá mostrar-lhe onde todos os seus moldes são, para que possa verificar se algum deles são incorretos.

Então, daqui para frente, se você compilar regularmente o código com C ++, ele irá forçar o uso de um elenco apropriado. Por exemplo, se você usar strip_qual apenas para remover um const ou volatile, mas o programa de mudanças na maneira como a de que uma conversão de tipo agora está envolvido, você vai ter um diagnóstico, e você terá que usar uma combinação de moldes para obter o conversão desejada.

Para ajudá-lo a aderir a estas macros, a ++ (! Não C) o compilador GNU C tem um belo recurso:. Um diagnóstico opcional que é produzido para todas as ocorrências de moldes estilo C

     -Wold-style-cast (C++ and Objective-C++ only)
         Warn if an old-style (C-style) cast to a non-void type is used
         within a C++ program.  The new-style casts (dynamic_cast,
         static_cast, reinterpret_cast, and const_cast) are less vulnerable
         to unintended effects and much easier to search for.

Se seus compila o código C como C ++, você pode usar esta opção -Wold-style-cast para descobrir todas as ocorrências da sintaxe fundição (type) que podem insinuar-se o código, e acompanhar esses diagnósticos, substituindo-o com uma escolha adequada de entre os acima macros (ou uma combinação, se necessário).

Este tratamento de conversões é a maior justificativa técnica autónoma única para trabalhar em um "Clean C":. O C e C ++ dialeto combinado, que por sua vez tecnicamente justifica lançando o valor de retorno de malloc

A melhor coisa a fazer quando programando em C sempre que possível:

  1. Faça a sua compilação programa através de um compilador C com todos os avisos ligado -Wall e corrigir todos os erros e avisos
  2. Certifique-se de que não há variáveis ??declaradas como auto
  3. Em seguida, compilá-lo usando um compilador C ++ com -Wall e -std=c++11. Corrigir todos os erros e avisos.
  4. Agora compilar usando o compilador C novamente. Seu programa deve agora compilar sem qualquer aviso e contêm menos erros.

Este procedimento permite que você tire vantagem de C ++ tipo de verificação rigorosa, reduzindo assim o número de bugs. Em particular, este procedimento obriga a incluir stdlib.hor você receberá

malloc não foi declarada neste âmbito

e também força você a converter o resultado de malloc ou você receberá

conversão inválida de void* para T*

ou o que nunca o seu tipo de alvo.

Os únicos benefícios da escrita em C em vez de C ++ que eu posso encontrar são

  1. C tem um bem especificado ABI
  2. C ++ pode gerar mais código [exceções, RTTI, modelos, tempo de execução polimorfismo]

Note que o segundo contras devem, no caso ideal desaparecem quando se utiliza o subconjunto comum para C em conjunto com o estático característica polimórfica.

Para aqueles que encontra C ++ estrita regras inconveniente, podemos usar o C ++ 11 recurso com o tipo inferido

auto memblock=static_cast<T*>(malloc(n*sizeof(T))); //Mult may overflow...

Não, você não converter o resultado de malloc().

Em geral, você não lançam para ou a partir void * .

Um motivo comum dada para não fazê-lo é que a falta de #include <stdlib.h> poderia passar despercebida. Este não é um problema mais por um longo tempo agora como C99 fez declarações de função implícitas ilegal, por isso, se o seu compilador está em conformidade com pelo menos C99, você receberá uma mensagem de diagnóstico.

Mas há um razão muito mais forte não introduzir pointer cast desnecessários:

Em C, a ponteiro elenco é quase sempre um erro . Isto é devido a seguinte regra ( §6.5 p7 em N1570, o mais recente projecto de C11):

Um objeto deve ter um valor armazenado acessado apenas por uma expressão lvalue que tem uma das os seguintes tipos:
- um tipo compatível com o tipo efectiva do objecto,
- uma versão qualificada de um tipo compatível com o tipo efectiva do objecto,
- um tipo que é a assinatura ou tipo sem sinal correspondente para o tipo efectivo do objeto,
- um tipo que é o assinaram ou tipo sem sinal correspondente a uma versão qualificada do Tipo efectiva do objecto,
- um tipo de agregado ou união que inclui um dos tipos acima mencionados entre os seus membros (incluindo, de forma recursiva, um membro de uma subaggregate ou união contida), ou
-. Um tipo de caractere

Este é também conhecido como o regra estrita aliasing . Então, o seguinte código é comportamento indefinido :

long x = 5;
double *p = (double *)&x;
double y = *p;

E, por vezes, surpreendentemente, o seguinte é assim:

struct foo { int x; };
struct bar { int x; int y; };
struct bar b = { 1, 2};
struct foo *p = (struct foo *)&b;
int z = p->x;

Às vezes, você do necessidade de ponteiros do elenco, mas dado o regra estrita aliasing , você tem que ter muito cuidado com ele. Assim, qualquer ocorrência de um elenco ponteiro em seu código é um lugar que você tem que verificar novamente para a sua validade . Portanto, você nunca escrever um elenco ponteiro desnecessário.

tl; dr

Em poucas palavras: Porque em C, qualquer ocorrência de um ponteiro elenco deve levantar uma bandeira vermelha para o código que requer uma atenção especial, você nunca deve escrever desnecessário pointer cast.


notas laterais:

  • Há casos em que você realmente necessidade um molde para void *, por exemplo, se você quiser imprimir um ponteiro:

    int x = 5;
    printf("%p\n", (void *)&x);
    

    O elenco é necessária aqui, porque printf() é uma função aridade variável, de modo conversões implícitas não fazer o trabalho.

  • Em C ++, a situação é diferente. Fundição tipos de ponteiro é pouco comum (e correcta) quando se lida com objectos de classes derivadas. Portanto, faz sentido que em C ++, a conversão de e para void * é não implícito. C ++ tem um conjunto de diferentes sabores de casting.

Eu prefiro fazer o elenco, mas não manualmente. O meu favorito é usando g_new e g_new0 macros de glib. Se simplista não é usado, gostaria de acrescentar macros semelhantes. Essas macros reduzir a duplicação de código sem comprometer a segurança de tipos. Se você obter o tipo errado, você deseja obter uma conversão implícita entre ponteiros não-vazios, o que causaria um aviso (erro em C ++). Caso se esqueça de incluir o cabeçalho que define g_new e g_new0, você obteria um erro. g_new e g_new0 ambos tomam os mesmos argumentos, ao contrário malloc que leva menos argumentos do que calloc. Basta adicionar 0 para obter memória de zero-inicializado. O código pode ser compilado com um compilador C ++, sem alterações.

A carcaça é somente para C ++ não caso C.In você estiver usando um compilador C ++ é melhor você alterá-lo para o compilador C.

O conceito por trás ponteiro void é que ele pode ser escalado a qualquer tipo de dados que é por isso que malloc retorna void. Além disso, você deve estar ciente de typecasting automática. Portanto, não é obrigatório para converter o ponteiro que você deve fazê-lo. Ele ajuda a manter o código limpo e ajuda a depuração

  1. Como outros declarou, não é necessário para C, mas para C ++.

  2. Incluindo o fundido pode permitir que um programa ou função C para compilar como C ++.

  3. Em C é desnecessário, como void * é automaticamente e com segurança promovido a qualquer outro tipo de ponteiro.

  4. Mas se você lançar em seguida, ele pode esconder um erro se você se esqueceu de incluir stdlib.h . Isso pode causar falhas (ou, pior ainda, não causar um acidente até meio depois, em alguma parte totalmente diferente do código).

    Como stdlib.h contém o protótipo para malloc é encontrado. No ausência de um protótipo para malloc, o padrão requer que o C compilador assume retornos malloc um int. Se não houver um elenco, um aviso é emitido quando esse número inteiro é atribuído ao ponteiro; no entanto, com o elenco, este aviso não é produzido, escondendo um bug.

Um ponteiro nulo é um ponteiro genérico e C suporta a conversão implícita de um tipo de ponteiro void para outros tipos, por isso não há necessidade de typecasting-lo explicitamente.

No entanto, se você quer o mesmo código de trabalho perfeitamente compatível em uma plataforma C ++, que não suporta a conversão implícita, você precisa fazer o typecasting, então tudo depende de usabilidade.

O casting de malloc é desnecessário em C, mas obrigatória em C ++.

A carcaça é desnecessária em C devido a:

  • void * é automaticamente e com segurança promovido a qualquer outro tipo de ponteiro no caso de C.
  • Pode esconder um erro se você se esqueceu de incluir <stdlib.h>. Isso pode causar falhas.
  • Se ponteiros e inteiros são de tamanhos diferentes, então você está escondendo um aviso por vazamento e pode perder pedaços de seu endereço retornado.
  • Se o tipo do ponteiro é alterado a sua declaração, pode-se também necessário alterar todas as linhas onde malloc é chamado e elenco.

Por outro lado, a carcaça pode aumentar a portabilidade do seu programa. ou seja, ele permite que um programa ou função C para compilar como C ++.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top