• Jobs
  • About Us
  • professionals
    • Home
    • Jobs
    • Courses and challenges
    • Questions
    • Teachers
  • business
    • Home
    • Post vacancy
    • Our process
    • Pricing
    • Assessments
    • Payroll
    • Blog
    • Sales
    • Salary Calculator

0

199
Views
Indexación de una variable 'larga sin signo' e impresión del resultado

Ayer, alguien me mostró este código:

 #include <stdio.h> int main(void) { unsigned long foo = 506097522914230528; for (int i = 0; i < sizeof(unsigned long); ++i) printf("%u ", *(((unsigned char *) &foo) + i)); putchar('\n'); return 0; }

Eso da como resultado:

 0 1 2 3 4 5 6 7

Estoy muy confundido, principalmente con la línea en el ciclo for . Por lo que puedo decir, parece que &foo se está convirtiendo en un unsigned char * y luego lo agrega i . Creo que *(((unsigned char *) &foo) + i) es una forma más detallada de escribir ((unsigned char *) &foo)[i] , pero esto hace que parezca foo , se está indexando un unsigned long . Si es así, ¿por qué? El resto del bucle parece típico de imprimir todos los elementos de una matriz, por lo que todo parece indicar que esto es cierto. El elenco de unsigned char * me confunde aún más. Intenté buscar sobre convertir tipos enteros a char * específicamente en Google, pero mi investigación se atascó después de algunos resultados de búsqueda inútiles sobre convertir int a char , itoa() , etc. 506097522914230528 imprime específicamente 0 1 2 3 4 5 6 7 , pero otros números parecen tener sus propios 8 números únicos que se muestran en la salida, y los números más grandes parecen llenar más ceros.

about 3 years ago · Santiago Trujillo
1 answers
Answer question

0

Como prefacio, este programa no necesariamente se ejecutará exactamente como lo hace en la pregunta, ya que exhibe un comportamiento definido por la implementación. Además de esto, ajustar ligeramente el programa también puede causar un comportamiento indefinido. Más información sobre esto al final.

La primera línea de la función main define un unsigned long foo como 506097522914230528 . Esto parece confuso al principio, pero en hexadecimal se ve así: 0x0706050403020100 .

Este número consta de los siguientes bytes: 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 . A estas alturas, probablemente pueda ver su relación con la salida. Si todavía está confundido acerca de cómo se traduce esto en la salida, eche un vistazo al bucle for.

 for (int i = 0; i < sizeof(unsigned long); ++i) printf("%u ", *(((unsigned char *) &foo) + i));

Suponiendo que un long tiene 8 bytes, este ciclo se ejecuta ocho veces (recuerde, dos dígitos hexadecimales son suficientes para mostrar todos los valores posibles de un byte, y dado que hay 16 dígitos en el número hexadecimal, el resultado es 8, por lo que el ciclo for corre ocho veces). Ahora la parte realmente confusa es la segunda línea. Piénselo de esta manera: como mencioné anteriormente, dos dígitos hexadecimales pueden mostrar todos los valores posibles de un byte, ¿verdad? Entonces, si pudiéramos aislar los dos últimos dígitos de este número, ¡obtendríamos un valor de byte de siete! Ahora, suponga que long es en realidad una matriz que se ve así:

 {00, 01, 02, 03, 04, 05, 06, 07}

Obtenemos la dirección de foo con &foo , la convertimos en un unsigned char * para aislar dos dígitos, luego usamos la aritmética de punteros para obtener básicamente foo[i] si foo es una matriz de ocho bytes. Como mencioné en mi pregunta, esto probablemente parece menos confuso como ((unsigned char *) &foo)[i] .


Un poco de advertencia: este programa exhibe un comportamiento definido por la implementación . Esto significa que este programa no necesariamente funcionará de la misma manera/dará el mismo resultado para todas las implementaciones de C. No solo es un largo de 32 bits en algunas implementaciones, sino que cuando declaramos el unsigned long , la forma/el orden en que almacena los bytes de 0x0706050403020100 (también conocido como endianness ) también están definidos por la implementación. Crédito a @philipxy por señalar primero el comportamiento definido por la implementación. Este tipo de juego de palabras causa otro problema que señaló @Ruslan, que es que, si el long se convierte en algo que no sea un char * / unsigned char * , entra en juego la estricta regla de alias de C y obtendrá un comportamiento indefinido (Crédito del el enlace también va a @Ruslan). Más detalles sobre estos dos puntos en la sección de comentarios.

about 3 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Our process Sales
Legal
Terms and conditions Privacy policy
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recommend me some offers
I have an error