2009-11-02 15 views
5

Cuando creas un entero con ceros a la izquierda, ¿cómo lo maneja c? ¿Es diferente para las diferentes versiones de C?¿Cómo maneja C Literal enteros con ceros a la izquierda, y qué pasa con atoi?

En mi caso, sólo parecen estar disminuido (pero tal vez eso es lo que hace printf?):

#include <stdio.h> 

int main() { 
    int a = 005; 
    printf("%i\n", a); 
    return 0; 
} 

Sé que puedo usar printf para rellenar con 0s, pero sólo me pregunto cómo este trabajos.

+1

Agregado "literal", porque en binario, cada int positivo tiene un cero inicial. – MSalters

+0

excepción de enteros sin signo mayor que 'UINT_MAX/2' :) – bdonlan

Respuesta

30

Los ceros a la izquierda indican que el número se expresa en octal, o base 8; por lo tanto, 010 = 8. La adición de ceros a la izquierda adicionales no tiene ningún efecto; tal como se esperaría en matemáticas, x + 0 * 8^n = x; no hay cambio en el valor al hacer que su representación sea más larga.

Un lugar que a menudo se ve en los modos de archivo UNIX; 0755 en realidad significa 7 * 8^2 + 5 * 8 + 5 = 493; o con umasks tales como 0022 = 2 * 8 + 2 = 10.

atoi(nptr) se define como equivalente a strtol(nptr, (char **) NULL, 10), excepto que no detecta errores - como tal, atoi() siempre utiliza decimal (y por tanto ignora los ceros iniciales). strtol(nptr, anything, 0) hace lo siguiente:

La cadena puede comenzar con una cantidad arbitraria de espacio en blanco (como se determina por isspace(3)) seguido de un único opcional '+' o '-' señal. Si base es cero o 16, la cadena puede entonces incluir un prefijo "0x", y el número se leerá en la base 16; de lo contrario, una base cero se toma como 10 (decimal) a menos que el siguiente carácter sea '0', en cuyo caso se toma como 8 (octal).

Por lo tanto, utiliza las mismas reglas que el compilador de C.

+0

Gracias, tal vez esta sea una pregunta diferente, pero con atoi o strtol sin una base de cero, ¿qué ocurre con los ceros a la izquierda? –

+0

¡Lo entiendo perfectamente ahora, gracias! Estoy seguro de que esto está en todos mis libros C básicos, simplemente no me pegó en la cabeza :-P –

1

Los números enteros no tienen "ceros a la izquierda" a 5 es un 5, puede escribir su representación de cadena con 0 delante si lo desea, para eso tiene los modificadores printf.

+1

sí, pero 010 no es – tvanfosson

+1

10. No he dicho que se trataba de la misma. Obviamente, sus intenciones eran agregar 0s, no usar octal. –

+0

No era tan obvio para mí, ya que indicó que ya sabía que podía rellenar con 0 en la salida. Obviamente, los enteros tienen 0 principales cuando quieres expresarlos en notación octal. – tvanfosson

7

¡Cuidado!

En esta instrucción, 005 es una constante octal.

int a = 005; 

En este caso no importa porque una sola constante octal dígito tiene el mismo valor que la constante decimal equivalente pero en C: 015 != 15

Ya sea un número entero literal se expresa en octal, decimal o hexadecimal, una vez que el compilador lo analiza, simplemente se trata como un valor. La salida de un entero a través de printf depende únicamente de su tipo, su valor y los especificadores de formato (y la configuración regional activa).

+0

pero printf usa decimal. – Behrooz

+1

@behrooz: imprime decimal 5, porque decimal y octal 5 tienen el mismo valor. Esto no es cierto para 010 y 10. Imprima el primero y obtendrá 8 (la representación de la cadena decimal de 1000 binario u octal 010).Imprima el segundo y obtendrá 10 (1010 binario u octal 012). – tvanfosson

5

Un número con cero significa la codificación octal en todas las versiones de C. Así que 011 == 9 == 0x9.

Octal es un sistema de numeración basado en 8 (en lugar de 10 para decimal o 16 para hexadecimal). Entonces 011 == 1*8 + 1, 013 == 1*8 + 3, etc.

0

En su caso particular, los ceros se van a descartar por printf. El compilador elimina todos los ceros a la izquierda, excepto el cero inicial, que hace que el compilador trate el entero como octal. Para 005, las representaciones octales y decimales son las mismas y no deberían molestarlo, pero aún así, está pidiendo problemas a menos que se refiera específicamente a la representación octal.

ceros iniciales tienen que ver únicamente con la representación de cadena del número entero. Para imprimir con ceros a la izquierda, use "% 03d". Esto asegurará una longitud de campo de 3.

En general, "% <x> d" imprimirá un entero x caracteres de ancho y se rellenará con espacios iniciales. "% 0 <x> d" hará lo mismo pero se rellenará con ceros a la izquierda.

+0

-1, los ceros a la izquierda no son "eliminados por printf". Los literales en el origen se convierten en una representación binaria (sin ningún concepto de ceros a la izquierda) por el compilador. printf no tiene idea de cómo se representó el valor en la fuente. –

+0

Punto tomado. Corregido –

3

debería probar:

int a = 5; 
printf("%03i\n", a); 

0 significa "almohadilla con ceros", 3 es la longitud deseada de salida.

Edit: Disculpa, leí tu pregunta demasiado rápido, ahora veo que has preguntado por algo completamente diferente. Sin embargo, lo dejo tal como está, ya que podría ser útil para otra persona.

5

El hecho de que un cero indica un número es octal es algo que a menudo se olvida. Lo he visto varias causar confusión veces, como cuando alguien trató de introducir una dirección IP utilizando un formato amigable, regular para los octetos:

192.168.010.073 

y el analizador interpretado los últimos 2 octetos como números octales.

La única cosa peor que lamentable el uso de C de los ceros iniciales para hacer un octal número es el manejo de Javascript de ceros iniciales a veces hacer una octal número (el número es octal si el resto de los dígitos son bien - a menos de 8 - decimal de lo contrario). En Javascript, (017 == 15) pero (018 == 18).

prefiero no ser un error; de hecho, preferiría dejar por completo el soporte literal octal. Al menos usar un prefijo más en-su-cara, como tal vez

0t10 (ocTal 8) 
0k17 (oKtal 15) 

Pero estoy cerca de 35 años de retraso con mi propuesta.

Cuestiones relacionadas