C - salin karakter nilai ASCII ke bilangan bulat 64bit

Seperti kita ketahui bersama, setiap karakter yang dapat dicetak memiliki nilai ascii masing-masing. Saya mencoba nilai ascii 8 karakter menjadi bilangan bulat 64 bit, tetapi hanya menyalin 32 bit.

char * ch = "AAAABBBB";
unsigned long int i;

//copy charater's ascii to 64 bits int
memcpy(&i, ch, 8);
printf("integer hold: 0x%x\n", i); 

Apakah ada yang salah dengan kode ini?

Output yang saya harapkan adalah:

integer hold: 0x4141414142424242

tetapi hasilnya adalah:

integer hold: 0x41414141

person REALFREE    schedule 05.02.2013    source sumber
comment
Tingkatkan peringatan Anda!   -  person Carl Norum    schedule 05.02.2013
comment
@CarlNorum Dan apa sebenarnya solusinya? Sejauh menyangkut kompiler, kode ini baik-baik saja.   -  person Lundin    schedule 05.02.2013
comment
@Lundin, string format printf yang tidak cocok menyebabkan perilaku tidak terdefinisi. GCC dan dentang akan mendeteksi dan memperingatkan tentang masalah ini. Dentang bahkan memberikan solusi yang disarankan!   -  person Carl Norum    schedule 06.02.2013
comment
@CarlNorum Di mana string format yang tidak cocok? GCC -Wall tidak memberikan apa pun, saya juga tidak melihat ada yang salah dengan kode ini, kecuali pilihan yang buruk dalam mendeklarasikan pointer ke string literal sebagai non-const. Mencetak variabel long yang tidak ditandatangani dengan %x bukanlah perilaku yang tidak terdefinisi, meskipun long lebih besar dari int. Sejauh yang saya tahu, mengambil bagian dari unsigned long, untuk alasan apa pun, selalu terdefinisi dengan baik dan tidak akan mengarah pada representasi jebakan apa pun.   -  person Lundin    schedule 06.02.2013
comment
%x untuk unsigned int, bukan unsigned long int. Ketidakcocokan selalu tidak ditentukan, meskipun salah satu atau semua implementasi menghasilkan sesuatu yang wajar. Saya akan mengambil keluaran peringatan dan menempelkannya di sini saat berikutnya saya menggunakan komputer.   -  person Carl Norum    schedule 06.02.2013
comment
@Lundin, dari dentang untuk program pengujian sederhana: example.c:6:20: peringatan: format menentukan tipe 'unsigned int' tetapi argumennya memiliki tipe 'unsigned long' [-Wformat] Dan dari GCC: example.c:6 : peringatan: format '%x' mengharapkan tipe 'unsigned int', tetapi argumen 2 memiliki tipe 'long unsigned int'. Selain peringatan, clang memberikan saran untuk mengganti %x dengan %lx.   -  person Carl Norum    schedule 06.02.2013
comment
@Lundin, saya harus mencatat bahwa saya bahkan tidak perlu mengaktifkan tanda -W apa pun. Pesan-pesan ini dihasilkan secara default dengan GCC 4.2.1 (yang lama, saya tahu, tapi saya menggunakan Mac) dan dentang 3.2.   -  person Carl Norum    schedule 06.02.2013


Jawaban (3)


Jika unsigned long memang bertipe 64-bit (Anda dapat menampilkan sizeof(unsigned long) untuk memeriksanya), Anda masih perlu menggunakan string berformat %lx untuk mencetaknya.

Jika unsigned long adalah 32 bit, Anda mungkin harus menggunakan unsigned long long dan menggunakan string format %llx.

Dari C11 7.20.6.1 The fprintf function:

o,u,x,X Argumen int unsigned diubah menjadi oktal unsigned (o), desimal unsigned (u), atau notasi heksadesimal unsigned (x atau X) dalam gaya dddd; huruf abcdef digunakan untuk konversi x dan huruf ABCDEF untuk konversi X. Presisi menentukan jumlah minimum digit yang akan muncul; jika nilai yang dikonversi dapat direpresentasikan dalam digit yang lebih sedikit, nilai tersebut diperluas dengan angka nol di depannya. Presisi defaultnya adalah 1. Hasil konversi nilai nol dengan presisi nol adalah tidak ada karakter.

l (ell): Menentukan bahwa penentu konversi d, i, o, u, x, atau X berikut berlaku untuk argumen long int atau unsigned long int.

ll (ell-ell): Menentukan bahwa penentu konversi d, i, o, u, x, atau X berikut berlaku untuk argumen long long int atau unsigned long long int.

person paxdiablo    schedule 05.02.2013

long versus long long.

Di VC++ tipe data long masih hanya 32 bit.

Dan tentu saja, format printf %x digunakan untuk int yaitu 32 bit di sebagian besar platform. Anda ingin %llx (atau mungkin %lx jika long Anda sudah 64 bit).

person Some programmer dude    schedule 05.02.2013
comment
Saya berbicara tentang C, bukan VC++. Dan saya sudah memeriksa ukuran unsigned long int yaitu 8 byte. - person REALFREE; 05.02.2013
comment
@REALFREE Silakan lihat jawaban saya yang diperbarui. Dan Anda tidak menentukan kompilernya, hanya bahasanya (dan bahasa C memungkinkan kompiler memiliki panjang bit yang berbeda untuk beberapa tipe) - person Some programmer dude; 05.02.2013
comment
%u dan %x saling eksklusif, %ullx akan menghasilkan desimal yang tidak diketahui diikuti dengan string llx literal. x menurut definisi tidak ditandatangani. Format yang benar adalah %llx atau %lx. - person paxdiablo; 05.02.2013
comment
Bagaimana dengan 4 byte menjadi 64 bit? Misalnya, c = AAAA dan salin ke unsigned long int. Saya pikir itu akan menjadi 0x00000041414141 dengan format 0x%16lx tetapi muncul seperti 0x 41414141 dengan ruang kosong. - person REALFREE; 05.02.2013
comment
@REALFREE Anda ingin mengatur lebar bidang. Silakan lihat printf referensi. - person Some programmer dude; 05.02.2013
comment
@REALFREE, Anda perlu mengisinya dengan angka nol, bukan spasi. Gunakan %016lx (perhatikan angka nol di depan). - person paxdiablo; 05.02.2013

%x digunakan untuk mencetak nilai int unsigned & 32 bitnya, itulah mengapa Anda mendapatkan hasil seperti itu.

%d %i     Decimal signed integer.
%o        Octal integer.
%x %X     Hex integer.
%u        Unsigned integer.
%c        Character.
%s        String.
%f        double
%e %E     double.
%g %G     double.
%p        pointer.

& jika ingin mencetak sisa data coba...

int *p;
p=(char *)(&i)+4;

printf("integer hold: 0x%x\n", i);
printf("integer hold: 0x%x\n",*p);
person akp    schedule 05.02.2013