[ccppbrasil] NULL vs 0

4 views
Skip to first unread message

Hugo Parente Lima

unread,
Apr 21, 2010, 4:01:28 PM4/21/10
to ccppb...@googlegroups.com
> É um assunto meio polêmico. Realmente acho que o nullptr (ou algo semelhante
> mas com outro nome) deveria ter sido considerado padrão C++ a muito tempo. A
> maioria dos programadores deve utilizar o NULL.
>
> O que eu acho engraçado é que o próprio Stroustrup, junto com Ellis
> (Annotated C++ Reference Manual), escreveu sobre o assunto, dizendo que é
> recomendável evitar-se o NULL, pois não há 100% de certeza quando a sua
> implementação em todos os casos, e que em alguns casos ele pode ser definido
> como (void*)0. Alguém aí já teve algum problema desse tipo? De qualquer
> forma, talvez seja precipitado considerar o uso do 0 como prática amadora
> (sei que talvez não seja isso que você quis dizer exatamente). Alguém aí
> utiliza 0 ao invés de NULL?

Sempre usei 0 e *nunca* tive problemas, acho C'ismo pensar que usar 0 ao invés
da macro NULL seja algo amador. Para não dizer que estou sozinho, o pessoal do
KDE[1] também usa 0 ao invés de NULL, bem, na verdade eles recomendam que você
use o que achar melhor, por que em C++ isso acaba sendo uma questão de
preferência pessoal e não técnica, eis a explicação deles:

You may notice that null pointers are marked variously in one of three ways:
0, 0L and NULL. In C, NULL is defined as a null void pointer. However, in C++,
this is not possible due to stricter type checking. Therefore, modern C++
implementations define it to a "magic" null pointer constant which can be
assigned to any pointer. Older C++ implementations, OTOH, simply defined it to
0L or 0, which provides no additional type safety - one could assign it to an
integer variable, which is obviously wrong.

In pointer context, the integer constant zero means "null pointer" -
irrespective of the actual binary representation of a null pointer. This means
that the choice between 0, 0L and NULL is a question of personal style and
getting used to something rather than a technical one - as far as the code in
KDE's SVN goes you will see 0 used more commonly than NULL.

Note, however, that if you want to pass a null pointer constant to a function
in a variable argument list, you *must* explicitly cast it to a pointer - the
compiler assumes integer context by default, which might or might not match
the binary representation of a pointer. Again, it does not matter whether you
cast 0, 0L or NULL, but the shorter representation is generally preferred.

[1]
http://techbase.kde.org/Development/Tutorials/Common_Programming_Mistakes#NULL_pointer_issues

> Acho que o melhor mesmo seria padronizar um nullptr, como está sendo feito,
> só que a preocupação da maioria é que já seja tarde demais para isso agora
> que o NULL está consolidado e presente em quase todo lugar.
>
> André.
>
--
Hugo Parente Lima
INdT - Instituto Nokia de Tecnologia

--
Hugo Parente Lima
INdT - Instituto Nokia de Tecnologia
"Precisamos de mais gênios humildes no mundo, hoje somos poucos!"

signature.asc

Felipe Magno de Almeida

unread,
Apr 22, 2010, 9:39:12 AM4/22/10
to ccppb...@googlegroups.com
Hugo Parente Lima <hug...@gmail.com> writes:

>> É um assunto meio polêmico. Realmente acho que o nullptr (ou algo semelhante
>> mas com outro nome) deveria ter sido considerado padrão C++ a muito tempo. A
>> maioria dos programadores deve utilizar o NULL.
>>
>> O que eu acho engraçado é que o próprio Stroustrup, junto com Ellis
>> (Annotated C++ Reference Manual), escreveu sobre o assunto, dizendo que é
>> recomendável evitar-se o NULL, pois não há 100% de certeza quando a sua
>> implementação em todos os casos, e que em alguns casos ele pode ser definido
>> como (void*)0. Alguém aí já teve algum problema desse tipo? De qualquer
>> forma, talvez seja precipitado considerar o uso do 0 como prática amadora
>> (sei que talvez não seja isso que você quis dizer exatamente). Alguém aí
>> utiliza 0 ao invés de NULL?
>
> Sempre usei 0 e *nunca* tive problemas, acho C'ismo pensar que usar 0 ao invés
> da macro NULL seja algo amador. Para não dizer que estou sozinho, o pessoal do
> KDE[1] também usa 0 ao invés de NULL, bem, na verdade eles recomendam que você
> use o que achar melhor, por que em C++ isso acaba sendo uma questão de
> preferência pessoal e não técnica, eis a explicação deles:

Concordo. Uma constante de valor zero em C++ é especial em que ela pode
significar um ponteiro nulo ou um inteiro. Esconder atrás de uma macro
não ajuda.

void foo(int);
void foo(int*);

int main()
{
foo(0);
foo(NULL);
}

Ambos são ambíguos e abstrair numa macro não vai ajudar quem encontrar o
erro.
Não condeno o uso de NULL, pois ele tende a dar enfase no código. Mas eu
pessoalmente prefiro evitar o uso de macros onde possível e portanto uso
o literal 0.
Considero que seja melhor usar o literal 0 sabendo dessas intrincacies
do C++, do que usar NULL e achar que isso resolve qualquer coisa.

[snip]

> --
> Hugo Parente Lima
> INdT - Instituto Nokia de Tecnologia

--
Antes de enviar um e-mail para o grupo leia:
http://www.ccppbrasil.org/wiki/Lista:AntesdePerguntar
--~--~---------~--~----~---------------------------------~----------~--~----~
[&] Colabore com a Pesquisa de Preferência de Conteúdo
para Eventos do Grupo C & C++ Brasil:
http://www.surveymonkey.com/s/GBBGTXN
------~----~-------~---~---~---~---~----------------~------------~---------~
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
Para mais opções, visite http://groups.google.com/group/ccppbrasil
--~--~---------~--~----~--~-~--~---~----~-----------------~--~----------~
Emprego & carreira: vag...@ccppbrasil.org
http://groups.google.com/group/dev-guys?hl=en

Wanderley Caloni

unread,
Apr 22, 2010, 12:13:07 PM4/22/10
to ccppbrasil
O único problema que poderia existir seria a possibilidade do endereço
0x00000000 ser válida em alguma arquitetura específica (<a
href="http://www.caloni.com.br/blog/archives/quando-o-ponteiro-nulo-
nao-e-invalido">como já foi visto algumas vezes</a>). Mas, como já foi
citado:

"In pointer context, the integer constant zero means "null pointer" -
irrespective of the actual binary representation of a null pointer."

O que encerra a questão =)

[]s

On Apr 22, 10:39 am, Felipe Magno de Almeida
<felipe.alme...@tqtvd.com> wrote:
> [&] C & C++ Brasil -http://www.ccppbrasil.org/
> Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
> Para mais opções, visitehttp://groups.google.com/group/ccppbrasil
> --~--~---------~--~----~--~-~--~---~----~-----------------~--~----------~
> Emprego & carreira:  vaga...@ccppbrasil.orghttp://groups.google.com/group/dev-guys?hl=en

André Santee

unread,
Apr 22, 2010, 12:26:01 PM4/22/10
to ccppb...@googlegroups.com
Neste caso o nullptr é importante somente para desambiguação.

André.

Jardel Weyrich

unread,
Apr 22, 2010, 12:32:52 PM4/22/10
to ccppb...@googlegroups.com
Acredito que na maioria dos sistemas é possível mapear o endereço 0x0, tornando-o um endereço válido.

No linux por exemplo, só é necessário alterar o valor do /proc/sys/vm/mmap_min_addr para 0 antes de mapear:

mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);

Inclusive, é assim que os recentes bugs de NULL-pointer-dereference são/foram explorados.

2010/4/22 Wanderley Caloni <wanderl...@gmail.com>

Rodrigo Strauss

unread,
Apr 22, 2010, 1:12:56 PM4/22/10
to ccppb...@googlegroups.com
Mas a questão do nullptr não é o valor, e sim o tipo. Diferenciar um ponteiro com valor 0 de um inteiro com valor 0.

Rodrigo Strauss
http://www.1bit.com.br


2010/4/22 Jardel Weyrich <jwey...@gmail.com>

Joaquim Junior

unread,
Apr 22, 2010, 2:25:23 PM4/22/10
to ccppb...@googlegroups.com
Amigos, estou acompanhando essa polemica desde o outro tópico. Eu queria conhecer outros exemplos que podem ocorrer problemas usando zero no lugar de NULL ou NULL no lugar de zero( tirando esse exemplo "O único problema que poderia existir seria a possibilidade do endereço 0x00000000 ser válida em alguma arquitetura específica"), alguém pode dar mais exemplos?

Eu acho que quando estamos envolvidos num projeto temos que estar cientes das diferenças de arquitetura e compilador. Nem sempre isso é fácil, muito gente fala sobre as vantagens de C++ ser uma linguagem padronizada; mas sempre estamos rodeados desses detalhes de algum ponto diferente na implementação da linguagem.

Gianni

unread,
Apr 22, 2010, 2:39:04 PM4/22/10
to ccppb...@googlegroups.com
Eu citei aqui um exemplo, onde eu herdei do std::string e criei construtores que recebiam const char* ou int.  Se NULL for definido como 0, ao invés de (void*)0, então, ao invés de um string em branco, eu recebia um "0";

O Adriano citou outro, onde ele passava ao printf o NULL.

Adriano dos Santos Fernandes

unread,
Apr 22, 2010, 2:56:48 PM4/22/10
to ccppb...@googlegroups.com
On 22/04/2010 15:39, Gianni wrote:
> Eu citei aqui um exemplo, onde eu herdei do std::string e criei
> construtores que recebiam const char* ou int. Se NULL for definido
> como 0, ao invés de (void*)0, então, ao invés de um string em branco,
> eu recebia um "0";
>
> O Adriano citou outro, onde ele passava ao printf o NULL.
>
Na verdade o erro era quando passava 0. NULL no GCC é __null, e essa
coisa vira um 0L, que em Linux 64 bits tem 64 bits de tamanho. Se vc
tentar passar um NULL no printf com um tipo incorreto vai ver o warning
referente a isso.

Dei uma olhada no bug original, e ele acontecia apenas quando era
passado dois zeros seguidos pra função variadic. Mas como alguém disse
ou eu li por aí, mesmo usando NULL o correto é fazer um cast para um
tipo de ponteiro nesse caso, pois não se tem uma garantia se ele expande
para 0, 0L ou um ((void*) 0).

Independente disso, minha opção foi sempre pelo NULL. Mas não uso coisas
como "if (x == NULL)" e sim "if (!x)".

Isso acaba sendo uma questão de estilo.

Uma coisa que me irrita, mas não tem a ver com o NULL agora, é ver
coisas como "if (strcmp(...))" ou "if (!strcmp(...))", ou seja, tratando
um inteiro como boolean. Mas tem gente que prefere, e é totalmente
válido em C/C++ (infelizmente, na minha opinião)...


Adriano

Marcio Gil

unread,
Apr 22, 2010, 3:27:55 PM4/22/10
to ccppb...@googlegroups.com
Não há diferença no C++, em termos de compilação, entre 0 e NULL,
já que o NULL sempre é transformado em 0 (será que existe uma
exceção em alguma plataforma?).
 
Só considero o NULL útil para o leitor humano, que logo sabe se o
código se refere a ponteiro ou a um número, porém sem nenhum
efeito para o compilador.
 
E como não faz diferença para o compilador, nunca soube de nenhum
motivo prático para não utilizar o NULL. Pelo contrário, pois
agrega mais clareza.
 


From: ccppb...@googlegroups.com [mailto:ccppb...@googlegroups.com] On Behalf Of Joaquim Junior
Sent: Thursday, April 22, 2010 3:25 PM
To: ccppb...@googlegroups.com
Subject: Re: [ccppbrasil] Re: NULL vs 0

Gianni

unread,
Apr 22, 2010, 3:42:51 PM4/22/10
to ccppb...@googlegroups.com

On Apr 22, 2010, at 4:27 PM, Marcio Gil wrote:

> Não há diferença no C++, em termos de compilação, entre 0 e NULL,
> já que o NULL sempre é transformado em 0 (será que existe uma
> exceção em alguma plataforma?).

Sim há. No meu stddef.h por exemplo:

#if defined (_STDDEF_H) || defined (__need_NULL)
#undef NULL /* in case <stdio.h> has defined it. */
#ifdef __GNUG__
#define NULL __null
#else /* G++ */
#ifndef __cplusplus
#define NULL ((void *)0)
#else /* C++ */
#define NULL 0
#endif /* C++ */
#endif /* G++ */
#endif /* NULL not defined and <stddef.h> or need NULL. */
#undef __need_NULL


Veja que NULL pode ser '0', '__null' ou '((void*)0)'.

No meu projeto que está aberto agora, está sendo definido como '__null'. Em outras plataformas (SH4 acho), recebo ((void*)0), e em alguns mais raros, 0.

Marcio Gil

unread,
Apr 22, 2010, 3:55:31 PM4/22/10
to ccppb...@googlegroups.com


> -----Original Message-----
> From: Gianni
>
> On Apr 22, 2010, at 4:27 PM, Marcio Gil wrote:
>
> > Não há diferença no C++, em termos de compilação, entre 0 e
NULL,
> > já que o NULL sempre é transformado em 0 (será que existe uma
> > exceção em alguma plataforma?).
>
> Sim há. No meu stddef.h por exemplo:
>
> #if defined (_STDDEF_H) || defined (__need_NULL)
> #undef NULL /* in case <stdio.h> has defined it. */
> #ifdef __GNUG__
> #define NULL __null
> #else /* G++ */
> #ifndef __cplusplus
> #define NULL ((void *)0)
> #else /* C++ */
> #define NULL 0
> #endif /* C++ */
> #endif /* G++ */
> #endif /* NULL not defined and <stddef.h> or need NULL. */
> #undef __need_NULL
>
>
> Veja que NULL pode ser '0', '__null' ou '((void*)0)'.
>
Sei... NULL só é ((void*)0) quando __cplusplus não está definido,
por isso eu disse "Não há diferença no C++", não entrei na questão
da linguagem C.

E quanto ao __null, o que ele é? Alguem aqui no grupo disse que pode
ser 0L, que diferença faria pro compilador entre isso e o literal 0?

No entanto, se há diferença, então é mais um ponto para o NULL, pois
aí é o compilador que decide o que é mais adequado para representar
um ponteiro nulo.

> No meu projeto que está aberto agora, está sendo definido
> como '__null'. Em outras plataformas (SH4 acho), recebo
> ((void*)0), e em alguns mais raros, 0.
>

O ((void*)0) não costuma ser utilizado no C++ porque a linguagem,
pelo penos no padrão, não suporta conversão automática de void* para
outros tipos de ponteiro.

Gianni

unread,
Apr 22, 2010, 4:18:16 PM4/22/10
to ccppb...@googlegroups.com
On Apr 22, 2010, at 4:55 PM, Marcio Gil wrote:
Sei... NULL só é ((void*)0) quando __cplusplus não está definido,
por isso eu disse "Não há diferença no C++", não entrei na questão
da linguagem C.

E quanto ao __null, o que ele é? Alguem aqui no grupo disse que pode
ser 0L, que diferença faria pro compilador entre isso e o literal 0?

No entanto, se há diferença, então é mais um ponto para o NULL, pois
aí é o compilador que decide o que é mais adequado para representar
um ponteiro nulo.

Justamente esse é o problema.  Eu escrevo código esperando que NULL seja um 'void*'.  

NULL não deveria ser um 0, acho isso uma falha do padrão.  NULL deveria ser a ausência de valor.  Quando o código é compilado e vira ASM, aí cada plataforma pode usar a representação binária que convier.  A maioria usaria 0, óbvio, e como foi mencionando aqui, em plataformas que 0 pode ser um endereço válido, poderia ser INT32_MAX/INT32_MIN, ou algo assim.  Eu estou agora trabalhando em uma plataforma com endereços de 24bits, logo um simples '2147483648' resolve (em binário, é apenas o bit mais significativo como 1).

Como disse, eu acho que NULL deveria ser um keyword, do mesmo jeito que 'false' é.  Ambos virariam 0 em ASM n maioria dos casos, mas isso não é algo necessariamente definido pelo padrão. 


No meu projeto que está aberto agora, está sendo definido
como '__null'.  Em outras plataformas (SH4 acho), recebo
((void*)0), e em alguns mais raros, 0.


O ((void*)0) não costuma ser utilizado no C++ porque a linguagem,
pelo penos no padrão, não suporta conversão automática de void* para
outros tipos de ponteiro.

Usando o mesmo argumento, um int (0) não pode ser automaticamente convertido para um T*.


Marcio Gil

unread,
Apr 22, 2010, 4:45:49 PM4/22/10
to ccppb...@googlegroups.com
---- Mensagem original ----
> From: Gianni
>
> On Apr 22, 2010, at 4:55 PM, Marcio Gil wrote:
> > Sei... NULL só é ((void*)0) quando __cplusplus não está
> > definido, por isso eu disse "Não há diferença no C++", não
> > entrei na questão da linguagem C.
> >
> > E quanto ao __null, o que ele é? Alguem aqui no grupo disse
> > que pode ser 0L, que diferença faria pro compilador entre
> > isso e o literal 0?
> >
> > No entanto, se há diferença, então é mais um ponto para o
> > NULL, pois aí é o compilador que decide o que é mais adequado
> > para representar um ponteiro nulo.
> >
>
> Justamente esse é o problema. Eu escrevo código esperando que
> NULL seja um 'void*'.
>

Só espere por isso se estiver programando em C99. Veja mais
detalhes aqui:

http://david.tribble.com/text/cdiffs.htm#C99-void-ptr

> NULL não deveria ser um 0, acho isso uma falha do padrão. NULL
> deveria ser a ausência de valor.

É impressão minha ou você espera que o C++ se comporte como a
linguagem SQL, com 1, 0 e NULL tento significados distintos?

Implementar isso no C++ acrescentaria um overhead que não seria
tolerado pelos desenvolvedores do C++. Creio que existam
linguagens mais adequadas caso este recurso seja necessário.
(Mas se eu estiver viajando, por favor, desconsidere :-)

> Quando o código é compilado e vira ASM, aí cada plataforma
> pode usar a representação binária que convier. A maioria
> usaria 0, óbvio, e como foi mencionando aqui, em plataformas
> que 0 pode ser um endereço válido, poderia ser
> INT32_MAX/INT32_MIN, ou algo assim. Eu estou agora trabalhando
> em uma plataforma com endereços de 24bits, logo um simples
> '2147483648' resolve (em binário, é apenas o bit mais
> significativo como 1).
>
> Como disse, eu acho que NULL deveria ser um keyword, do mesmo
> jeito que 'false' é. Ambos virariam 0 em ASM n maioria dos
> casos, mas isso não é algo necessariamente definido pelo
> padrão.
>

Para o NULL não dá mais, pois traria muitas incompatibilidades.
Já o nullptr é algo novo, só há risco de incompatibilidade para
quem utiliza esta palavra como identificador.

> > > No meu projeto que está aberto agora, está sendo definido
> > > como '__null'. Em outras plataformas (SH4 acho), recebo
> > > ((void*)0), e em alguns mais raros, 0.
> >
> > O ((void*)0) não costuma ser utilizado no C++ porque a
> > linguagem, pelo penos no padrão, não suporta conversão
> > automática de void* para outros tipos de ponteiro.
>
> Usando o mesmo argumento, um int (0) não pode ser
> automaticamente convertido para um T*.
>

Pode sim pois 0 é um literal cujo tipo é determinado pelo contexto.

Acredito que o problema de conversão a partir de void* na
linguagem C++ seja pela existência da herança. A regra é que um
ponteiro para uma classe base pode apontar com segurança para uma
classe derivada, mas o contrário não é seguro, e por isso existe
o static_cast, dynamic_cast, etc.

Seguindo o mesmo raciocínio um ponteiro para void pode apontar
com segurança para qualquer tipo de ponteiro, mas nada garante
que o inverso seja seguro, é o programador que deve decidir
fazendo o cast explícito para o tipo correto.

Quem tiver maior conhecimento do padrão me corrija se falei algo
errado.

Gianni

unread,
Apr 22, 2010, 5:05:03 PM4/22/10
to ccppb...@googlegroups.com

On Apr 22, 2010, at 5:45 PM, Marcio Gil wrote:

> ---- Mensagem original ----
>> From: Gianni
>>
>> On Apr 22, 2010, at 4:55 PM, Marcio Gil wrote:
>>> Sei... NULL só é ((void*)0) quando __cplusplus não está
>>> definido, por isso eu disse "Não há diferença no C++", não
>>> entrei na questão da linguagem C.
>>>
>>> E quanto ao __null, o que ele é? Alguem aqui no grupo disse
>>> que pode ser 0L, que diferença faria pro compilador entre
>>> isso e o literal 0?
>>>
>>> No entanto, se há diferença, então é mais um ponto para o
>>> NULL, pois aí é o compilador que decide o que é mais adequado
>>> para representar um ponteiro nulo.
>>>
>>
>> Justamente esse é o problema. Eu escrevo código esperando que
>> NULL seja um 'void*'.
>>
>
> Só espere por isso se estiver programando em C99. Veja mais
> detalhes aqui:
>
> http://david.tribble.com/text/cdiffs.htm#C99-void-ptr
>
>> NULL não deveria ser um 0, acho isso uma falha do padrão. NULL
>> deveria ser a ausência de valor.
>
> É impressão minha ou você espera que o C++ se comporte como a
> linguagem SQL, com 1, 0 e NULL tento significados distintos?

Não espero, mas gostaria. E não, eu estava pensando em matemática, mas SQL tem sim o mesmo conceito para NULL.

> Implementar isso no C++ acrescentaria um overhead que não seria
> tolerado pelos desenvolvedores do C++. Creio que existam
> linguagens mais adequadas caso este recurso seja necessário.
> (Mas se eu estiver viajando, por favor, desconsidere :-)

Não necessariamente. Pode ser feito apenas como um tipo especial. Aliás, o efeito é exatamente o que o nullptr faz.

>
>> Quando o código é compilado e vira ASM, aí cada plataforma
>> pode usar a representação binária que convier. A maioria
>> usaria 0, óbvio, e como foi mencionando aqui, em plataformas
>> que 0 pode ser um endereço válido, poderia ser
>> INT32_MAX/INT32_MIN, ou algo assim. Eu estou agora trabalhando
>> em uma plataforma com endereços de 24bits, logo um simples
>> '2147483648' resolve (em binário, é apenas o bit mais
>> significativo como 1).
>>
>> Como disse, eu acho que NULL deveria ser um keyword, do mesmo
>> jeito que 'false' é. Ambos virariam 0 em ASM n maioria dos
>> casos, mas isso não é algo necessariamente definido pelo
>> padrão.
>>
>
> Para o NULL não dá mais, pois traria muitas incompatibilidades.
> Já o nullptr é algo novo, só há risco de incompatibilidade para
> quem utiliza esta palavra como identificador.

Estava falando em uma situação idealizada. Se isso fosse feito literalmente, eu ficaria puto! ;-)

>
>>>> No meu projeto que está aberto agora, está sendo definido
>>>> como '__null'. Em outras plataformas (SH4 acho), recebo
>>>> ((void*)0), e em alguns mais raros, 0.
>>>
>>> O ((void*)0) não costuma ser utilizado no C++ porque a
>>> linguagem, pelo penos no padrão, não suporta conversão
>>> automática de void* para outros tipos de ponteiro.
>>
>> Usando o mesmo argumento, um int (0) não pode ser
>> automaticamente convertido para um T*.
>>
>
> Pode sim pois 0 é um literal cujo tipo é determinado pelo contexto.

Estava falando de int p/ T*.

Por exemplo, isso não pode:

int x = 0;
FOO *foo = x;

Ou seja, converter um int p/ T* não pode, mas existe a gambiarra de que 0, que é int, pode; mas só se for literal. Logo, converter ((void*)0) para T*, é uma gambiarra menor que 0 p/ T.

O ponto é: é uma gambiarra (0 -> T*), e uma 'falha' no padrão que foi aceita para compatibilidade com C. Até aí, tudo bem. Mas do mesmo jeito 0 -> bool é aceito, e ainda assim existe o keyword 'false', que o C não tem, deveriamos ter um NULL/null/qqr coisa que fosse um T* sem valor.

Marcio Gil

unread,
Apr 22, 2010, 5:56:37 PM4/22/10
to ccppb...@googlegroups.com
Nativamente, só o double teria este conceito. Poderíamos utilizar
o std::numeric_limits<double>::quiet_NaN() para representar o
NULL.

Fiz uma experiência aqui:

#include <iostream>
#include <limits>

int main()
{
double x = 0;
double y = 1;
double z = std::numeric_limits<double>::quiet_NaN();
double a, b, c, d;

a = x*y;
b = y*z;
c = x+y;
d = y+z;
std::cout << "a=" << a << ", b=" << b
<< ", c=" << c << ", d=" << d << std::endl;
std::cout << (a<=b?" a<=b":b<=a?" a<=b":" a??b");
std::cout << (a<=c?" a<=c":b<=c?" a<=c":" a??c");
std::cout << (a<=d?" a<=d":b<=d?" a<=d":" a??d");
std::cout << std::endl;

return 0;
}

Resulta:

$ g++ nan.cpp
$ ./a.out
a=0, b=nan, c=1, d=nan
a??b a<=c a??d

Para outros tipos, ou separaríamos um valor especial para
representar o NULL (o que me parece arriscado), ou precisaríamos
de um flag qualquer que nos indicasse isso. Fosse qual fosse a
implementação do NULL, a cada operação precisaria antes verificar
se um dos operandos é nulo (aí está o overhead de que falei).

Se isto for realmente necessário já é possível então criar uma
classe, nullable_integer por exemplo, com todos os operadores
necessários (isto se já não existe algo por aí), mas esta é uma
questão que foge um pouco do tópico.

> (...)
> >
> >>>> No meu projeto que está aberto agora, está sendo definido
> >>>> como '__null'. Em outras plataformas (SH4 acho), recebo
> >>>> ((void*)0), e em alguns mais raros, 0.
> >>>
> >>> O ((void*)0) não costuma ser utilizado no C++ porque a
> >>> linguagem, pelo penos no padrão, não suporta conversão
> >>> automática de void* para outros tipos de ponteiro.
> >>
> >> Usando o mesmo argumento, um int (0) não pode ser
> >> automaticamente convertido para um T*.
> >>
> >
> > Pode sim pois 0 é um literal cujo tipo é determinado pelo
contexto.
>
> Estava falando de int p/ T*.
>
> Por exemplo, isso não pode:
>
> int x = 0;
> FOO *foo = x;
>
> Ou seja, converter um int p/ T* não pode, mas existe a
> gambiarra de que 0, que é int, pode; mas só se for literal.
> Logo, converter ((void*)0) para T*, é uma gambiarra menor que 0 p/
T.
>

Posso estar enganado, mas acho que é o contexto que determina o
tipo do valor literal, então o 0 em um contexto que espera char*
é do tipo char* e não do tipo int.

> O ponto é: é uma gambiarra (0 -> T*), e uma 'falha' no padrão
> que foi aceita para compatibilidade com C. Até aí, tudo bem.
> Mas do mesmo jeito 0 -> bool é aceito, e ainda assim existe
> o keyword 'false', que o C não tem, deveriamos ter um
> NULL/null/qqr coisa que fosse um T* sem valor.
>

Não só o literal 0 pode ser do tipo bool, como um int é
convertido automaticamente para bool, ao contrário dos ponteiros
pois um int não é convertido automaticamente para ponteiro.

O tipo bool x int é uma questão de compabilidade muito mais séria
pois existia (e ainda existe) muitíssimo código que utiliza
variáveis do tipo int para armazenar um booleano.

Marcio Gil

unread,
Apr 22, 2010, 6:00:42 PM4/22/10
to ccppb...@googlegroups.com
Errata:

#include <iostream>
#include <limits>

int main()
{
double x = 0;
double y = 1;
double z = std::numeric_limits<double>::quiet_NaN();
double a, b, c, d;

a = x*y;
b = y*z;
c = x+y;
d = y+z;
std::cout << "a=" << a << ", b=" << b
<< ", c=" << c << ", d=" << d << std::endl;
std::cout << (a<=b?" a<=b":b>=a?" a>=b":" a??b");
std::cout << (a<=c?" a<=c":b>=c?" a>=c":" a??c");
std::cout << (a<=d?" a<=d":b>=d?" a>=d":" a??d");
std::cout << std::endl;

return 0;
}

Mas o resultado é o mesmo:

$ g++ nan.cpp
$ ./a.out
a=0, b=nan, c=1, d=nan
a??b a<=c a??d


Felipe Magno de Almeida

unread,
Apr 23, 2010, 11:23:52 AM4/23/10
to ccppb...@googlegroups.com
Gianni <nasus....@gmail.com> writes:

> On Apr 22, 2010, at 5:45 PM, Marcio Gil wrote:
>
>> ---- Mensagem original ----

[snip]

>> Pode sim pois 0 é um literal cujo tipo é determinado pelo contexto.
>
> Estava falando de int p/ T*.
>
> Por exemplo, isso não pode:
>
> int x = 0;
> FOO *foo = x;
>
> Ou seja, converter um int p/ T* não pode, mas existe a gambiarra de
> que 0, que é int, pode; mas só se for literal. Logo, converter
> ((void*)0) para T*, é uma gambiarra menor que 0 p/ T.

Na verdade:

int *p = (5 - 5);

Também é valido. É uma constante de valor 0, não necessariamente o
literal 0.

[snip]

--
Felipe magno de Almeida
Reply all
Reply to author
Forward
0 new messages