Esto es MUUUY sutil
On Thu, Feb 23, 2012 at 3:54 PM, Daniel Gutson <daniel...@gmail.com> wrote:
> --
> ¿Eres miembro de "CyC++ Buenos Aires" verdad? Si no lo eres, has recibido
> este mesaje por error.
> En caso de duda visita "http://groups.google.com/group/cppba"
--
Fernando Cacciola
SciSoft Consulting, Founder
http://www.scisoft-consulting.com
Agrego otra de este estilo que me paso:
char a = 0xFF (esto salia de un ifstream binario)
int b = a;
Mi idea era q b == 0xFF :(
[esto tiene tela para cortar]
Vayamos por parte:
>
> o hacemos if ( c == -1 )
>
Usar -1 en lugar de 0xFF es decididamente un paso adelante, pero, no
es solo por lo que vos empiricamente viste que pasa:
Veamos:
(1)
char c = -1 ;
char magic = 0xFF ;
if ( c == magic )
Ya no hay ninguna conversión implícita haciendo lio, pero, anda?
NO lo prueben porque van a llegar a la conclusión equivocada, salvo
que tengan un máquina poco convensional.
Por otro lado, tu version es equivalente a esto:
(2)
char c = -1 ;
if ( (int)(c) == -1 )
Seguro que anda?
De nuevo no lo prueben, salvo que el compilador perfectamente legal lo
hayan hecho a proposito para demotrar que....ç
>
> O bien c se define como unsigned char
>
Cuando esten resultos los dos puntos anteriores vuelvo sobre esto.
Dije que esto daba para rato :)
> con lo que la línea de código quedaría:
>
> if ( c == \xff )
>
Todavía quedan 'huecos' por resolver aún en esta versión.
Fijate la devolución a Eduardo.
> Una aclaración adicional:
>
> char, unsigned char y signed char son 3 tipos diferentes. Durante
> la conversión de char a int el compilador es libre de elegir si lo considera
> con signo o no, por lo tanto comparar contra -1 no es portable.
>
Ahí nos vamos acercando.
Efectivamente el -1 no es portable si convertimos el char a int.
Por otro lado, técnicamente, la dicotomía existe aún mas allá de la
conversión a entero.
Es decir:
char c0 = -1 ;
unsigned char c1 = -1 ;
signed chat c2 = -1 ;
if ( c0 == c1 )
if ( c0 == c2 ) ;
Alguno de los if() da true? Cuál?
OK, una pista entonces.
NO lo prueben porque les va a andar.. y sin embargo eso no quiere decir nada :)
P.S.:
Otra pista... C y C++, a diferencia de muchos otros lenguajes, está
pensado para permitir al programador escribir un fuente y correr el
programa resultante en cualquier cosa capaz de ser programada, y
entonces, esta DEFINIDO de un modo que haga eso posible.
Decimos entonces que la *especificación* del lenguaje (según un
determinado estandard) dice que las cosas son de uno y/o otro modo, y
es eso lo que debe ser considerado para decidir si el programa que
escribimos hace *garantizadamente* esto o aquello.
Saludos
ESO.
Entonces?
si char c = -1 ;
(int)(c) da o no da -1??
Ojo que complemento del x86 no es solo el mundo de los microcontroladores (*)
Por otro lado:
Lo que debemos saber es que:
un char puede, "internamente", ser un signed char o un unsigned char,
según lo defina el compilador.
(*)
Miren este listado de "arquitecturas" *que son todavía suficientemente
relevantes:
P.S.: Todavía falta el tema del (signed char)(-1) vs 0xFF
Buena pregunta:
signed/unsigned char son tipos enteros que sirven para representar
números enteros con o sin signo, mientras que char a secas, aunque
puede ser usado del mismo modo (tal como ocurre en la práctica),
existe en sí mismo como el tipo de dato que representa de un byte.
Es decir, un bloque de memoria, es decir el *storage* que le
corresponde a un *objeto* (o lvalue en C), está definido como una
secuencia de chars (y no como una secuencia de signed char o unsigned
char). Resulta entonces que necesitamos del tipo char como un tipo
diferente a signed/unsigned char para referir a bloques de memoria.
Ahora bien, si tenemos que tener esos tres tipos, y char tiene que
ser el que corresponde a un byte, porqué especificar si tiene que ser
con o sin signo en lugar de dejar a la implementación (o sea el
compilador) decidirlo?
Por otro lado, uno podria pensar que char podría no tener nada que ver
con signed or unsigned char y tener en cambio su propia definicion
independiente (que de todos modos no especificaria si puede o no
representar números negativos (*) para no forzar al compilador
innecesariamete)
.Net por ejemplo distingue explicitamente uno de otros:
http://msdn.microsoft.com/en-us/magazine/bb984984.aspx
Aunque hace explícito el tema del signo: byte es unsigned mientras que
sbyte es signed (en mi opninión esto es un error, pero...)
> ¿Por qué no exigir que el programador especifique el signo?
Acá está el quiz de la cuestón:
el verdadero propósito de char es,k o debería ser en mi opinión,
representar un byte. Y la arquitectura define el byte como se le da la
gana, incluso en cuanto a la cantidad de bits (sizeof(char)==8 no es
siempre cierto!)
Ahora, si el programador quiere representar números pequeños, debe, o
puede al menos, usar signed char or unsigned char, con lo cual está
especificando el signo como decis.
Que en la práctica se abuse de char para, por ejemplo, representar
caracteres en un archivo o string, es posiblemente un accidente
cultural (tal vez en K&R no había todavía signed char/unsigned char?
sería interesante investigar esto)
> ¿pasa lo mismo con integer, signed integer y unsigned integer?
>
NO
Para cualquier otro tipo de dato entero, signed está implicito:
typeof(signed int)==typeof(int), lo mismo para short, long, etc...
>
> Siguiendo con este razonamiento creería que (signed char)(-1) == 0xFF
> sería falso, ya que 0xFF es un entero positivo
> (¿las constantes por
> default son enteros con signo, no?)
Los *literales* (no constantes) son de un determinado tipo que depende
del la forma del literal, y sí, para el caso de "solo un número" (mas
allá de que sea decimal o hexdecimal), el tipo es signed int, que es
lo mismo que int.
1u por otro lado es un unsgined int, etc..
> y se castea el (signed char) -1 a
> signed integer, manteniendo el valor (-1).
>
Hmm, en realidad me equivoqué y quise preguntar por:
(unsigned char)(-1) == 0xFF
Eso es o no cierto?
[todavía hay un tema más que del cual no se habló para nada todavía]
Saludos
Y justamente a esto iba mi pregunta. Pero esta vez me voy a responder.
En C y C++ los números enteros no necesariamente tienen que usar
complemento a 2. Eso lo define el compilador de acuerdo a la
arquitectura que estamos usando.
Así, -1 puede ser 0xFF..FE (complemeto a 1) en lugar de 0xFF..FF
De hecho, hasta puede ser signo+magnitud (o sea con un bit de signo)
--
¿Eres miembro de "CyC++ Buenos Aires" verdad? Si no lo eres, has recibido este mesaje por error.
En caso de duda visita "http://groups.google.com/group/cppba"