conversion - Cadenas ASCII y endianness
little endian converter (13)
Pero sorprendentemente, el interno afirma que su profesor insiste en que la cuerda se representará como:
P-yM azzi
Sería representado como, representado como qué? representado al usuario como un volcado de enteros de 32 bits? o representado / diseño en la memoria de la computadora como P-yM azzi?
Si el profesor dijo que "My-Pizza" se representaría / diseño como "P-yM azzi" en la memoria de la computadora porque la computadora es de poca arquitectura endian, ¡alguien, por favor, debe enseñarle a ese profesor cómo usar un depurador! Creo que de ahí provienen todas las confusiones del profesor, tengo la sospecha de que el profesor no es codificador (no es que esté despreciando al profesor), creo que no tiene forma de demostrar en código lo que aprendió sobre endian-ness.
Tal vez el profesor aprendió el tema del endianismo hace apenas una semana, luego simplemente usó un depurador incorrectamente, rápidamente se deleitó con su nueva visión única en las computadoras y luego la predicó a sus alumnos de inmediato.
Si el profesor dijo que la endianidad de la máquina influye en cómo se representarían las cuerdas ascii en la memoria, necesita limpiar su acto, alguien debería corregirlo.
Si, en cambio, el profesor dio un ejemplo sobre cómo se representan los números enteros / el diseño en las máquinas de manera diferente según el endianness de la máquina, sus alumnos podrían apreciar de lo que está enseñando.
Una pasante que trabaja conmigo me mostró un examen que había tomado en informática sobre problemas de endianness. Hubo una pregunta que mostraba una cadena ASCII "Mi-Pizza", y el estudiante tuvo que mostrar cómo esa cadena se representaría en la memoria en una pequeña computadora endia. Por supuesto, esto suena como una pregunta capciosa porque las cadenas ASCII no se ven afectadas por los problemas endian.
Pero sorprendentemente, el interno afirma que su profesor insiste en que la cuerda se representará como:
P-yM azzi
Sé que esto no puede ser correcto. No hay forma de que una cadena ASCII se represente así en cualquier máquina. Pero aparentemente, el profesor insiste en esto. Entonces, escribí un pequeño programa de C y le dije al interno que se lo diera a su profesor.
#include <string.h>
#include <stdio.h>
int main()
{
const char* s = "My-Pizza";
size_t length = strlen(s);
for (const char* it = s; it < s + length; ++it) {
printf("%p : %c/n", it, *it);
}
}
Esto demuestra claramente que la cadena se almacena como "Mi Pizza" en la memoria. Un día más tarde, el pasante me responde y me dice que el profesor ahora afirma que C está convirtiendo automágicamente las direcciones para mostrar la cadena en el orden correcto.
Le dije que su profesor está loco, y esto está claramente mal. Pero solo para comprobar mi cordura aquí, decidí publicar esto en stackoverflow para poder hacer que otros confirmen lo que estoy diciendo.
Entonces, pregunto: ¿quién está aquí?
¿El código "C" del profesor se parece a esto? Si es así, necesita actualizar su compilador.
main() {
extrn putchar;
putchar(''Hell'');
putchar(''o, W'');
putchar(''orld'');
putchar(''!*n'');
}
AFAIK, endianness solo tiene sentido cuando quieres dividir un gran valor en pequeños. Por lo tanto, no creo que la cadena de estilo C se vea afectada. Porque, después de todo, solo son matrices de caracteres. Cuando estás leyendo solo un byte, ¿cómo podría importar si lo lees desde la izquierda o desde la derecha?
Además, (Y no he jugado con esto en mucho tiempo, así que podría estar equivocado). ¿Podría estar pensando en pascol, donde las cadenas se representan como "conjuntos empaquetados" que, IIRC son caracteres agrupados en enteros de 4 bytes?
El profesor está confundido. Para ver algo como ''P-yM azzi'' necesita tomar alguna herramienta de inspección de memoria que muestre la memoria en el modo ''entero de 4 bytes'' y al mismo tiempo le dé una ''interpretación de caracteres'' de cada entero en orden superior byte al modo byte de orden inferior.
Esto, por supuesto, no tiene nada que ver con la cadena en sí. Y decir que la cuerda misma está representada de esa manera en una máquina little-endian es una completa tontería.
El profesor está equivocado si hablamos de un sistema que usa 8 bits por carácter.
A menudo trabajo con sistemas integrados que realmente usan caracteres de 16 bits, siendo cada palabra little-endian. En un sistema de este tipo, la cadena "My-Pizza" se almacenaría como "yMP-ziaz".
Pero siempre que sea un sistema de 8 bits por carácter, la cadena siempre se almacenará como "Mi-Pizza" independientemente de la endianidad de la arquitectura de nivel superior.
Endianness define el orden de los bytes dentro de los valores de múltiples bytes. Las cadenas de caracteres son matrices de valores de un solo byte. Por lo tanto, cada valor (carácter en la cadena) es el mismo en las arquitecturas little-endian y big-endian, y la endianidad no afecta el orden de los valores en una estructura.
Es difícil leer la mente del prof y ciertamente el compilador no hace otra cosa que almacenar bytes en direcciones crecientes adyacentes en los sistemas BE y LE, pero es normal mostrar la memoria en números del tamaño de una palabra, sea cual sea el tamaño de la palabra, y escribimos mil como 1,000. No 000,1.
$ cat > /tmp/pizza
My-Pizza^D
$ od -X /tmp/pizza
0000000 502d794d 617a7a69
0000010
$
Para el registro, y == 79, M == 4d.
Me encontré con esto y sentí la necesidad de aclararlo. Nadie aquí parece haber abordado el concepto de byte
y word
o cómo address . Un byte es de 8 bits. Una word es una colección de bytes.
Si la computadora es:
- byte direccionable
- con palabras de 4 bytes (32 bits)
- palabra alineada
- la memoria se visualiza "físicamente" (no volcada ni intercambiada por bytes)
entonces, de hecho, el profesor estaría en lo cierto. Su fracaso al indicar esto demuestra que no sabe exactamente de lo que está hablando, pero entendió el concepto básico.
Orden de bytes dentro de las palabras: (a) Big Endian, (b) Little Endian
Carácter y datos enteros en palabras: (a) Big Endian, (b) Little Endian
Referencias
Puede demostrar con bastante facilidad que el compilador no realiza transformaciones "mágicas", haciendo la impresión en una función que no sabe que se ha pasado una cadena:
int foo(const void *mem, int n)
{
const char *cptr, *end;
for (cptr = mem, end = cptr + n; cptr < end; cptr++)
printf("%p : %c/n", cptr, *cptr);
}
int main()
{
const char* s = "My-Pizza";
foo(s, strlen(s));
foo(s + 1, strlen(s) - 1);
}
Demonios, incluso puedes compilar para ensamblar con gcc -S
y determinar definitivamente la ausencia de magia.
Puede que le interese, es posible emular una arquitectura little-endian en una máquina big-endian, o viceversa. El compilador tiene que emitir un código que se enreda automáticamente con los bits menos significativos de los caracteres char*
siempre que los desreferencia: en una máquina de 32 bits mapea 00 <-> 11 y 01 <-> 10.
Por lo tanto, si escribe el número 0x01020304
en una máquina big-endian y vuelve a leer el "primer" byte de esa dirección-munging, obtendrá el byte menos significativo, 0x04
. La implementación C es little-endian aunque el hardware es big-endian.
Necesitas un truco similar para accesos cortos. Los accesos no alineados (si se admiten) pueden no referirse a bytes adyacentes. Tampoco puede usar tiendas nativas para tipos de más de una palabra porque aparecerían intercambiadas por palabras cuando se leen de nuevo un byte a la vez.
Obviamente, sin embargo, las máquinas little-endian no hacen esto todo el tiempo, es un requisito muy especializado y te impide usar el ABI nativo. Me parece que el profesor piensa que los números reales son "en realidad" big-endian, y está profundamente confundido con lo que realmente es una arquitectura little-endian y / o cómo se está representando su memoria.
Es cierto que la cadena se "representa como" P-yM azzi
en máquinas de 32 bits, pero solo si por "representado" te refieres a "leer las palabras de la representación en orden de aumentar la dirección, pero imprimir los bytes de cada palabra grande- endian ". Como han dicho otros, esto es lo que algunas vistas de la memoria del depurador podrían hacer, por lo que es una representación del contenido de la memoria. Pero si va a representar los bytes individuales, entonces es más común listarlos en orden de aumentar la dirección, sin importar si las palabras se almacenan como be o le, en lugar de representar cada palabra como un literal de múltiples caracteres. Ciertamente no hay ningún toque de puntero, y si la representación elegida del profesor lo ha llevado a pensar que hay algo, entonces lo ha engañado.
Sin duda, tienes razón.
El estándar ANSI C 6.1.4 especifica que los literales de cadena se almacenan en la memoria "concatenando" los caracteres en el literal.
ANSI estándar 6.3.6 también especifica el efecto de adición en un valor de puntero:
Cuando una expresión que tiene un tipo integral se agrega o se resta de un puntero, el resultado tiene el tipo del operando del puntero. Si el operando puntero apunta a un elemento de un objeto de matriz, y la matriz es lo suficientemente grande, el resultado apunta a un desplazamiento de elemento desde el elemento original de modo que la diferencia de los subíndices de los elementos de matriz resultantes y originales es igual a la expresión integral.
Si la idea atribuida a esta persona era correcta, entonces el compilador también tendría que moverse con matemáticas enteras cuando los enteros se usan como índices de matriz. También se producirían muchas otras falacias que se dejan a la imaginación.
La persona puede estar confundida, porque (a diferencia de un inicializador de cadenas), las constantes de chapa multibyte como ''ABCD'' se almacenan en orden endian.
Hay muchas razones por las cuales una persona puede estar confundida acerca de esto. Como otros han sugerido aquí, puede estar malinterpretando lo que ve en una ventana del depurador, donde los contenidos han sido intercambiados en bytes para la legibilidad de los valores int.
Supongo que el profesor intentaba hacer una analogía sobre el problema endian / NUXI, pero tiene razón cuando lo aplica a cadenas reales. No dejes que eso se descarrile del hecho de que estaba tratando de enseñarle a los estudiantes un punto y cómo pensar sobre un problema de cierta manera.