Posso usar o NULL
ponteiro como substituto do valor de 0
?
Ou há algo de errado nisso?
Como por exemplo:
int i = NULL;
como substituto para:
int i = 0;
Como experimento, compilei o seguinte código:
#include <stdio.h>
int main(void)
{
int i = NULL;
printf("%d",i);
return 0;
}
Resultado:
0
De fato, ele me dá esse aviso, que é completamente correto por si só:
warning: initialization makes integer from pointer without a cast [-Wint-conversion]
mas o resultado ainda é equivalente.
- Estou entrando no "comportamento indefinido" com isso?
- É permitido utilizar
NULL
dessa maneira? - Há algo de errado em usar
NULL
como valor numérico em expressões aritméticas? - E qual é o resultado e o comportamento em C ++ para este caso?
Eu li as respostas de Qual é a diferença entre NULL, '\ 0' e 0 sobre qual é a diferença entre NULL
, \0
e 0
é, mas não recebi as informações concisas a partir daí, se é bastante permitido e correto usar NULL
como valor para operar em atribuições e outras operações aritméticas.
Respostas:
Não , não é seguro fazê-lo.
NULL
é uma constante de ponteiro nulo, que pode ter tipoint
, mas que normalmente tem tipovoid *
(em C) ou não é diretamente atribuível a umint
(em C ++> = 11). Os dois idiomas permitem que os ponteiros sejam convertidos em números inteiros, mas eles não permitem que essas conversões sejam executadas implicitamente (embora alguns compiladores o ofereçam como uma extensão). Além disso, embora seja comum converter um ponteiro nulo em um número inteiro para gerar o valor 0, o padrão não garante isso. Se você deseja uma constante com tipoint
e valor 0, soletre-a0
.Sim, em qualquer implementação em que se
NULL
expanda para um valor com o tipovoid *
ou qualquer outro não diretamente atribuívelint
. O padrão não define o comportamento de sua atribuição em tal implementação; portanto, seu comportamento é indefinido.É um estilo ruim, e irá quebrar em alguns sistemas e sob algumas circunstâncias. Na medida em que você parece estar usando o GCC, ele seria quebrado em seu próprio exemplo se você compilasse com a
-Werror
opçãoSim. Não é garantido que você tenha um valor numérico. Se você quer dizer 0, escreva 0, que não é apenas bem definido, mas mais curto e mais claro.
A linguagem C ++ é mais rígida em conversões do que em C e possui regras diferentes para
NULL
, mas também as implementações podem fornecer extensões. Novamente, se você quer dizer 0, é isso que deve escrever.fonte
void *
" é válido apenas para C.void *
não é um tipo legal para C ++ (porque você não pode atribuirvoid*
a nenhum outro tipo de ponteiro). No C ++ 89 e C ++ 03, de fato,NULL
deve ser do tipoint
, mas em versões posteriores pode ser (e geralmente é)nullptr_t
.void*
paraint
um comportamento indefinido. Não é; é um comportamento especificado de implementação.NULL
é alguma constante de ponteiro nulo. Em C, poderia ser uma expressão constante inteira com valor0
ou uma expressão lançada emvoid*
, com a última mais provável. O que significa que você não pode assumir o uso de formaNULL
intercambiável com zero. Por exemplo, neste exemplo de códigoA substituição
0
porNULL
não é garantida como um programa C válido, porque a adição entre dois ponteiros (sem falar em tipos diferentes de ponteiros) não está definida. Isso fará com que um diagnóstico seja emitido devido a uma violação de restrição. Os operandos para adição não serão válidos .Quanto ao C ++, as coisas são um pouco diferentes. A falta de uma conversão implícita de
void*
para outros tipos de objetos significava que elaNULL
era historicamente definida como0
no código C ++. No C ++ 03, você provavelmente poderia se safar. Mas desde o C ++ 11 ele pode sernullptr
legalmente definido como a palavra - chave . Agora, novamente, produzindo um erro, poisstd::nullptr_t
não pode ser adicionado aos tipos de ponteiro.Se
NULL
for definido como talnullptr
, mesmo sua experiência se tornará inválida. Não há conversão destd::nullptr_t
para um número inteiro. É por isso que é considerada uma constante de ponteiro nulo mais segura.fonte
NULL
nos dois idiomas.0
constante um ponteiro nulo: "evidentemente como um sopro para todo o código C existente, mal escrito, que fez suposições incorretas" #As regras variam entre os idiomas e suas versões. Em alguns casos, você pode e em outros, você não pode. Independentemente, você não deveria . Se você tiver sorte, seu compilador avisará quando você tentar ou, melhor ainda, não conseguir compilar.
Em C ++, anterior ao C ++ 11 (citação de C ++ 03):
Não faz sentido usar uma constante de ponteiro nulo como um número inteiro. Contudo...
Portanto, tecnicamente funcionaria mesmo que seja sem sentido. Devido a esse detalhe técnico, você pode encontrar programas mal escritos que abusam
NULL
.Desde C ++ 11 (citação do último rascunho):
A
std::nullptr_t
não é conversível em um número inteiro, portanto, usarNULL
como número inteiro funcionaria apenas condicionalmente, dependendo das escolhas feitas pela implementação do idioma.PS
nullptr
é um pré-valor do tipostd::nullptr_t
. A menos que você precise compilar seu programa no pré-C ++ 11, você deve sempre usar emnullptr
vez deNULL
.C é um pouco diferente (citações do rascunho C11 N1548):
Portanto, o caso é semelhante ao pós C ++ 11, ou seja, o abuso de
NULL
obras condicionalmente, dependendo das escolhas feitas pela implementação da linguagem.fonte
Sim , embora, dependendo da implementação, você possa precisar de uma conversão. Mas sim, é 100% legítimo, caso contrário.
Embora seja um estilo muito, muito, muito ruim (escusado será dizer?).
NULL
é, ou na verdade não é C ++, é C. O padrão , no entanto, como em muitos legados de C, possui duas cláusulas ([diff.null] e [support.types.nullptr]) que tecnicamente compõem oNULL
C ++. É uma constante de ponteiro nulo definida pela implementação . Portanto, mesmo que seja de estilo ruim, é tecnicamente o C ++ possível.Conforme apontado na nota de rodapé , possíveis implementações podem ser
0
ou0L
, mas não(void*)0
.NULL
poderia, é claro (o padrão não diz isso explicitamente, mas é praticamente a única opção que resta depois0
ou0L
)nullptr
. Quase nunca é o caso, mas é uma possibilidade legal.O aviso que o compilador mostrou a você demonstra que o compilador não é realmente compatível (a menos que você tenha compilado no modo C). Porque, bem, de acordo com o aviso, ele converteu um ponteiro nulo (não o
nullptr
que serianullptr_t
, o que seria distinto), então, aparentemente, a definição deNULL
é de fato(void*)0
, o que pode não ser.De qualquer forma, você tem dois possíveis casos legítimos (ou seja, o compilador não está quebrado). Ou (o caso realista),
NULL
é algo como0
ou0L
, então você tem "zero ou uma" conversão em número inteiro e está pronto para prosseguir.Ou
NULL
é de fatonullptr
. Nesse caso, você tem um valor distinto que garante garantias de comparação, bem como conversões claramente definidas de números inteiros, mas infelizmente não para números inteiros. No entanto, possui uma conversão claramente definida parabool
(resultando emfalse
) ebool
uma conversão claramente definida para número inteiro (resultando em0
).Infelizmente, são duas conversões, portanto, não está dentro de "zero ou um", como apontado em [conv]. Portanto, se sua implementação definir
NULL
comonullptr
, você precisará adicionar uma conversão explícita para que seu código esteja correto.fonte
Do FAQ C:
fonte
Disclaimer: Eu não sei C ++. Minha resposta não deve ser aplicada no contexto de C ++
'\0'
é umint
com valor zero, exatamente 100% exatamente como0
.No contexto de ponteiros ,
0
eNULL
são 100% equivalentes:são todos 100% equivalentes.
Nota sobre
ptr + NULL
O contexto de não
ptr + NULL
é o de ponteiros. Não há definição para a adição de ponteiros na linguagem C; ponteiros e números inteiros podem ser adicionados (ou subtraídos). Em se quer ou é um ponteiro, o outro deve ser um inteiro, então é efetivamente ou e, dependendo das definições de e vários comportamentos pode ser esperado: tudo trabalho, alertando para a conversão entre ponteiro e inteiro, a falta de compilar, .. .ptr + NULL
ptr
NULL
ptr + NULL
(int)ptr + NULL
ptr + (int)NULL
ptr
NULL
fonte
#define NULL (void *)0
antes. Tem certeza de que NULL e simples 0 são 100% equivalentes?ptr + NULL
não está usandoNULL
no contexto de ponteiros #nullptr
é, mas((void*)0)
e0
(ou'\0'
) são equivalentes no contexto de ponteiros ...if (ptr == '\0' /* or equivalent 0, NULL */)
Não, não é mais o preferido
NULL
(maneira antiga de inicialização do ponteiro).Desde o C ++ 11:
A palavra-chave
nullptr
denota o literal do ponteiro. É um pré-valor do tipo std :: nullptr_t. Existem conversões implícitas denullptr
para o valor do ponteiro nulo de qualquer tipo de ponteiro e qualquer ponteiro para o tipo de membro. Conversões semelhantes existem para qualquer constante de ponteiro nulo, que inclui valores do tipostd::nullptr_t
e da macroNULL
.https://en.cppreference.com/w/cpp/language/nullptr
Na verdade, std :: nullptr_t é o tipo do literal do ponteiro nulo
nullptr
,. É um tipo distinto que não é, por si só, um tipo de ponteiro ou um ponteiro para o tipo de membro.Resultado:
fonte