Apakah ada definisi makro satu baris untuk menentukan endianness mesin. Saya menggunakan kode berikut tetapi mengubahnya menjadi makro akan terlalu lama.
unsigned char test_endian( void )
{
int test_var = 1;
unsigned char *test_endian = (unsigned char*)&test_var;
return (test_endian[0] == 0);
}
c
architecture
macros
endianness
manav mn
sumber
sumber
0
bukannyaNULL
dalam tes akhir Anda, dan mengubah salah satutest_endian
objek menjadi yang lain :-).#if
arahan.Jawaban:
Kode yang mendukung urutan byte arbitrer, siap untuk dimasukkan ke dalam file bernama
order32.h
:Anda akan memeriksa sistem little endian melalui
sumber
char
? Lebih baik gunakanuint8_t
dan gagal jika jenis ini tidak tersedia (yang dapat diperiksa oleh#if UINT8_MAX
). Perhatikan bahwaCHAR_BIT
tidak bergantunguint8_t
.O32_HONEYWELL_ENDIAN = 0x02030001ul /* Honeywell 316 */
Jika Anda memiliki kompiler yang mendukung literal majemuk C99:
atau:
Secara umum, Anda harus mencoba menulis kode yang tidak bergantung pada endianness platform host.
Contoh implementasi host-endianness-independent dari
ntohl()
:sumber
ntohl
dengan cara yang tidak bergantung pada endianness platform host.Tidak ada standar, tetapi pada banyak sistem termasuk
<endian.h>
akan memberi Anda beberapa definisi untuk dicari.sumber
#if __BYTE_ORDER == __LITTLE_ENDIAN
dan#elif __BYTE_ORDER == __BIG_ENDIAN
. Dan menghasilkan elemen lain#error
.<endian.h>
tidak tersedia di Windowsendian.h
kecuali__APPLE__
atau_WIN32
ditentukan.#if BYTE_ORDER == LITTLE_ENDIAN
(atauBIG_ENDIAN
) tanpa garis bawah sebelum namanya._BYTE_ORDER
hanya untuk header sistem.__BYTE_ORDER
tidak ada.Untuk mendeteksi endianness pada waktu proses, Anda harus dapat merujuk ke memori. Jika Anda tetap menggunakan C standar, mendeklarasikan variabel dalam memori memerlukan pernyataan, tetapi mengembalikan nilai memerlukan ekspresi. Saya tidak tahu cara melakukan ini dalam satu makro — inilah alasan gcc memiliki ekstensi :-)
Jika Anda ingin memiliki file .h, Anda dapat menentukan
lalu Anda bisa menggunakan
ENDIANNESS
makro sesuka Anda.sumber
Jika Anda hanya ingin mengandalkan preprocessor, Anda harus mencari tahu daftar simbol yang telah ditentukan sebelumnya. Aritmatika preprocessor tidak memiliki konsep pengalamatan.
GCC di Mac mendefinisikan
__LITTLE_ENDIAN__
atau__BIG_ENDIAN__
Kemudian, Anda dapat menambahkan lebih banyak arahan bersyarat praprosesor berdasarkan deteksi platform seperti
#ifdef _WIN32
dll.sumber
#define __BIG_ENDIAN__ 1
dan#define _BIG_ENDIAN 1
.#define __LITTLE_ENDIAN__ 1
. Makro ini tampaknya merupakan fitur clang, bukan fitur gcc. Thegcc
perintah dalam beberapa Mac tidak gcc, itu dentang.Saya yakin inilah yang diminta. Saya hanya menguji ini pada mesin endian kecil di bawah pnidui. Seseorang mohon konfirmasi pada mesin big endian.
Sebagai catatan tambahan (khusus kompilator), dengan kompilator agresif Anda dapat menggunakan pengoptimalan "penghapusan kode mati" untuk mencapai efek yang sama seperti waktu kompilasi
#if
seperti ini:Hal di atas bergantung pada fakta bahwa kompilator mengenali nilai konstan pada waktu kompilasi, sepenuhnya menghapus kode di dalamnya
if (false) { ... }
dan mengganti kode sepertiif (true) { foo(); }
denganfoo();
skenario kasus terburuk: kompilator tidak melakukan pengoptimalan, Anda masih mendapatkan kode yang benar tetapi sedikit lebih lambat.sumber
'ABCD'
?clang -Wpedantic -Werror -Wall -ansi foo.c
dan itu akan error. (Dentang dan ini khusus:-Wfour-char-constants -Werror
)Jika Anda mencari tes waktu kompilasi dan Anda menggunakan gcc, Anda dapat melakukan:
Lihat dokumentasi gcc untuk informasi lebih lanjut.
sumber
__BYTE_ORDER__
tersedia sejak GCC 4.6Anda dapat di akses fakta memori dari objek sementara dengan menggunakan literal senyawa (C99):
GCC mana yang akan dievaluasi pada waktu kompilasi.
sumber
#if __STDC_VERSION__ >= 199901L
.'Perpustakaan jaringan C' menawarkan fungsi untuk menangani ketangguhan. Yaitu htons (), htonl (), ntohs () dan ntohl () ... di mana n adalah "jaringan" (mis. Big-endian) dan h adalah "host" (yaitu kesempurnaan mesin yang menjalankan kode).
'Fungsi' yang jelas ini (umumnya) didefinisikan sebagai makro [lihat <netinet / in.h>], jadi tidak ada overhead waktu proses untuk menggunakannya.
Makro berikut menggunakan 'fungsi' ini untuk mengevaluasi ketangguhan.
Sebagai tambahan:
Satu-satunya saat saya perlu mengetahui endian'ness dari suatu sistem adalah ketika saya menulis variabel [ke file / lainnya] yang dapat dibaca oleh sistem lain yang tidak diketahui endian'ness (untuk kompatibilitas lintas platform ) ... Dalam kasus seperti ini, Anda mungkin lebih suka menggunakan fungsi endian secara langsung:
sumber
Gunakan fungsi sebaris daripada makro. Selain itu, Anda perlu menyimpan sesuatu dalam memori yang merupakan efek samping makro yang tidak terlalu bagus.
Anda bisa mengubahnya menjadi makro pendek menggunakan variabel statis atau global, seperti ini:
sumber
s_endianess
disetel ke 1 untuk memulai?Meskipun tidak ada #define portabel atau sesuatu yang dapat diandalkan, platform menyediakan fungsi standar untuk mengonversi ke dan dari endian 'host' Anda.
Umumnya, Anda melakukan penyimpanan - ke disk, atau jaringan - menggunakan 'network endian', yang merupakan BIG endian, dan komputasi lokal menggunakan host endian (yang pada x86 disebut LITTLE endian). Anda menggunakan
htons()
danntohs()
dan teman untuk mengonversi di antara keduanya.sumber
sumber
Jangan lupa bahwa kesungguhan bukanlah keseluruhan cerita - ukuran
char
mungkin bukan 8 bit (mis. DSP), negasi pelengkap dua tidak dijamin (mis. Cray), penyelarasan ketat mungkin diperlukan (mis. SPARC, juga ARM muncul di tengah -endian saat tidak sejajar), dll, dll.Mungkin ide yang lebih baik untuk menargetkan arsitektur CPU tertentu sebagai gantinya.
Sebagai contoh:
Perhatikan bahwa solusi ini juga sayangnya tidak ultra-portabel, karena bergantung pada definisi khusus kompiler (tidak ada standar, tetapi berikut adalah kompilasi bagus dari definisi tersebut).
sumber
Coba ini:
sumber
Harap perhatikan bahwa sebagian besar jawaban di sini tidak portabel, karena penyusun hari ini akan mengevaluasi jawaban tersebut dalam waktu kompilasi (bergantung pada pengoptimalan) dan mengembalikan nilai tertentu berdasarkan endian tertentu, sedangkan endian mesin yang sebenarnya dapat berbeda. Nilai di mana endianness diuji, tidak akan pernah mencapai memori sistem sehingga kode yang dijalankan sebenarnya akan mengembalikan hasil yang sama terlepas dari endian yang sebenarnya.
untuk contoh , di ARM Cortex-M3 endianness diimplementasikan akan mencerminkan dalam AIRCR.ENDIANNESS Status bit dan compiler tidak dapat mengetahui nilai ini dalam waktu kompilasi.
Hasil kompilasi untuk beberapa jawaban yang disarankan di sini:
https://godbolt.org/z/GJGNE2 untuk jawaban ini ,
https://godbolt.org/z/Yv-pyJ untuk ini jawaban , dan seterusnya.
Untuk mengatasinya, Anda harus menggunakan
volatile
kualifikasi.Yogeesh H T
Jawabannya 's adalah yang paling dekat untuk penggunaan kehidupan nyata saat ini, tapi karenaChristoph
menyarankan solusi yang lebih komprehensif, memperbaiki sedikit untuk itu jawabannya akan membuat jawabannya lengkap, hanya menambahkanvolatile
untuk deklarasi union:static const volatile union
.Ini akan memastikan penyimpanan dan pembacaan dari memori, yang diperlukan untuk menentukan ketangguhan.
sumber
Jika Anda membuang preprocessor #defines
Anda biasanya dapat menemukan hal-hal yang akan membantu Anda. Dengan logika waktu kompilasi.
Namun, berbagai kompiler mungkin memiliki definisi yang berbeda.
sumber
Jawaban saya tidak seperti yang ditanyakan tetapi sangat mudah untuk mengetahui apakah sistem Anda little endian atau big endian?
Kode:
sumber
Kode C untuk memeriksa apakah suatu sistem adalah little-endian atau big-indian.
sumber
Makro untuk menemukan endiannes
atau
sumber