มีวิธีการเขียนโปรแกรมเพื่อตรวจสอบว่าคุณอยู่ในสถาปัตยกรรมขนาดใหญ่หรือเล็กหรือไม่? ฉันต้องสามารถเขียนโค้ดที่จะทำงานบนระบบ Intel หรือ PPC และใช้รหัสเดียวกันทุกประการ (เช่นไม่มีการคอมไพล์แบบมีเงื่อนไข)
มีวิธีการเขียนโปรแกรมเพื่อตรวจสอบว่าคุณอยู่ในสถาปัตยกรรมขนาดใหญ่หรือเล็กหรือไม่? ฉันต้องสามารถเขียนโค้ดที่จะทำงานบนระบบ Intel หรือ PPC และใช้รหัสเดียวกันทุกประการ (เช่นไม่มีการคอมไพล์แบบมีเงื่อนไข)
คำตอบ:
ฉันไม่ชอบวิธีการตามประเภทของ punning - มันมักจะถูกเตือนโดยคอมไพเลอร์ นั่นคือสิ่งที่สหภาพมีไว้เพื่อ!
bool is_big_endian(void)
{
union {
uint32_t i;
char c[4];
} bint = {0x01020304};
return bint.c[0] == 1;
}
หลักการนี้เทียบเท่ากับกรณีตัวพิมพ์ตามที่ผู้อื่นแนะนำ แต่ชัดเจนกว่าและตาม C99 นั้นรับประกันว่าถูกต้อง gcc ชอบสิ่งนี้มากกว่าเมื่อเทียบกับการส่งพอยน์เตอร์โดยตรง
นี่ยังดีกว่าการแก้ไข endianness ในเวลารวบรวม - สำหรับระบบปฏิบัติการที่รองรับหลายสถาปัตยกรรม (เช่นไบนารีไขมันบน Mac os x) ซึ่งจะทำงานได้ทั้ง ppc / i386 ในขณะที่มันง่ายที่จะทำสิ่งต่าง ๆ เป็นอย่างอื่น .
CHAR_BIT != 8
?
คุณสามารถทำได้โดยการตั้งค่าบิต int และการปิดบัง แต่วิธีที่ง่ายที่สุดคือการใช้ตัวแปลงไบต์เครือข่ายที่สร้างขึ้น (ตั้งแต่ลำดับไบต์เครือข่ายมักเป็นปลายทางขนาดใหญ่)
if ( htonl(47) == 47 ) {
// Big endian
} else {
// Little endian.
}
บิตซออาจจะเร็วกว่า แต่วิธีนี้ง่ายตรงไปตรงมาและเป็นไปไม่ได้ที่จะเลอะเทอะ
BSWAP
ดำเนินงาน
โปรดดูบทความนี้ :
นี่คือรหัสบางส่วนเพื่อพิจารณาประเภทของเครื่องของคุณ
int num = 1; if(*(char *)&num == 1) { printf("\nLittle-Endian\n"); } else { printf("Big-Endian\n"); }
คุณสามารถใช้std::endian
หากคุณมีสิทธิ์เข้าถึงคอมไพเลอร์ C ++ 20 เช่น GCC 8+ หรือ Clang 7+
หมายเหตุ: การstd::endian
เริ่มต้นใน<type_traits>
แต่ถูกย้ายไป<bit>
ที่ 2019 ประชุมโคโลญ GCC 8 เสียงดังกราว 7, 8 และ 9 มีมันอยู่ใน<type_traits>
ขณะที่ GCC 9+ และเสียงดังกราว 10+ <bit>
มีมันอยู่ใน
#include <bit>
if constexpr (std::endian::native == std::endian::big)
{
// Big endian system
}
else if constexpr (std::endian::native == std::endian::little)
{
// Little endian system
}
else
{
// Something else
}
โดยปกติจะทำในเวลาคอมไพล์ (โดยเฉพาะสำหรับเหตุผลด้านประสิทธิภาพ) โดยใช้ไฟล์ส่วนหัวที่มีให้จากคอมไพเลอร์หรือสร้างของคุณเอง บน linux คุณมีไฟล์ส่วนหัว "/usr/include/endian.h"
ฉันประหลาดใจที่ไม่มีใครพูดถึงมาโครที่ตัวประมวลผลล่วงหน้ากำหนดโดยค่าเริ่มต้น ในขณะที่สิ่งเหล่านี้จะแตกต่างกันไปขึ้นอยู่กับแพลตฟอร์มของคุณ พวกมันสะอาดกว่าการเขียนเช็คเอนเดียนของคุณเอง
ตัวอย่างเช่น; หากเราดูมาโครในตัวที่ GCC กำหนด (บนเครื่อง X86-64):
:| gcc -dM -E -x c - |grep -i endian
#define __LITTLE_ENDIAN__ 1
บนเครื่อง PPC ฉันได้รับ:
:| gcc -dM -E -x c - |grep -i endian
#define __BIG_ENDIAN__ 1
#define _BIG_ENDIAN 1
( :| gcc -dM -E -x c -
เวทย์มนตร์พิมพ์มาโครในตัวทั้งหมด)
echo "\n" | gcc -x c -E -dM - |& grep -i 'endian'
จะไม่ส่งคืนอะไรในขณะที่ gcc 3.4.3 (จากเดิม/usr/sfw/bin
) ใน Solaris มีคำจำกัดความตามบรรทัดเหล่านี้ ฉันเคยเห็นปัญหาที่คล้ายกันใน VxWorks Tornado (gcc 2.95) -vs- VxWorks Workbench (gcc 3.4.4)
อืม ... มันทำให้ฉันประหลาดใจที่ไม่มีใครรู้ว่าคอมไพเลอร์จะทำการทดสอบให้เหมาะสมและจะให้ผลลัพธ์ที่แน่นอนเป็นค่าตอบแทน นี่ทำให้ตัวอย่างโค้ดทั้งหมดข้างต้นไร้ประโยชน์อย่างมีประสิทธิภาพ สิ่งเดียวที่จะกลับมาคือ endianness ที่รวบรวมเวลา! และใช่ฉันทดสอบตัวอย่างข้างต้นทั้งหมด นี่คือตัวอย่างของ MSVC 9.0 (Visual Studio 2008)
รหัสเพียว C
int32 DNA_GetEndianness(void)
{
union
{
uint8 c[4];
uint32 i;
} u;
u.i = 0x01020304;
if (0x04 == u.c[0])
return DNA_ENDIAN_LITTLE;
else if (0x01 == u.c[0])
return DNA_ENDIAN_BIG;
else
return DNA_ENDIAN_UNKNOWN;
}
ถอดชิ้นส่วน
PUBLIC _DNA_GetEndianness
; Function compile flags: /Ogtpy
; File c:\development\dna\source\libraries\dna\endian.c
; COMDAT _DNA_GetEndianness
_TEXT SEGMENT
_DNA_GetEndianness PROC ; COMDAT
; 11 : union
; 12 : {
; 13 : uint8 c[4];
; 14 : uint32 i;
; 15 : } u;
; 16 :
; 17 : u.i = 1;
; 18 :
; 19 : if (1 == u.c[0])
; 20 : return DNA_ENDIAN_LITTLE;
mov eax, 1
; 21 : else if (1 == u.c[3])
; 22 : return DNA_ENDIAN_BIG;
; 23 : else
; 24 : return DNA_ENDIAN_UNKNOWN;
; 25 : }
ret
_DNA_GetEndianness ENDP
END
อาจเป็นไปได้ที่จะปิดการเพิ่มประสิทธิภาพเวลารวบรวมใด ๆ สำหรับฟังก์ชั่นนี้ แต่ฉันไม่รู้ มิฉะนั้นอาจเป็นไปได้ที่จะฮาร์ดโค้ดไว้ในชุดแม้ว่าจะไม่สามารถพกพาได้ และแม้แต่นั้นก็อาจได้รับการปรับให้เหมาะสม มันทำให้ฉันคิดว่าฉันต้องการแอสเซมบลีเส็งเคร็งจริง ๆ ใช้รหัสเดียวกันสำหรับซีพียู / ชุดคำสั่งที่มีอยู่ทั้งหมดและดี .... ไม่เป็นไร
นอกจากนี้บางคนที่นี่บอกว่า endianness ไม่เปลี่ยนแปลงในระหว่างเวลาทำงาน ไม่ถูกต้อง. มีเครื่องจักร bi-endian อยู่ที่นั่น endianness ของพวกเขาอาจแตกต่างกันไปการประหารชีวิต นอกจากนี้ยังมีไม่เพียง Endian น้อยและ Big Endian แต่ยัง endiannesses อื่น ๆ (คำ)
ฉันเกลียดและรักการเขียนโปรแกรมในเวลาเดียวกัน ...
ประกาศตัวแปร int:
int variable = 0xFF;
ตอนนี้ใช้ตัวชี้ถ่าน * เพื่อส่วนต่าง ๆ ของมันและตรวจสอบสิ่งที่อยู่ในส่วนเหล่านั้น
char* startPart = reinterpret_cast<char*>( &variable );
char* endPart = reinterpret_cast<char*>( &variable ) + sizeof( int ) - 1;
ในตอนนี้คุณสามารถตรวจจับ endianness ได้ขึ้นอยู่กับจุดใดจุดหนึ่งถึง 0xFF สิ่งนี้ต้องใช้ sizeof (int)> sizeof (char) แต่แน่นอนว่าเป็นจริงสำหรับแพลตฟอร์มที่กล่าวถึง
สำหรับรายละเอียดเพิ่มเติมคุณอาจต้องการตรวจสอบบทความCodeproject แนวคิดพื้นฐานเกี่ยวกับ Endianness :
วิธีการทดสอบ Endian type ณ รันไทม์แบบไดนามิก?
ตามที่อธิบายไว้ในคำถามที่พบบ่อยเกี่ยวกับภาพเคลื่อนไหวของคอมพิวเตอร์คุณสามารถใช้ฟังก์ชั่นต่อไปนี้เพื่อดูว่ารหัสของคุณกำลังทำงานอยู่ในระบบ Little- หรือ Big-Endian: ยุบ
#define BIG_ENDIAN 0 #define LITTLE_ENDIAN 1
int TestByteOrder()
{
short int word = 0x0001;
char *byte = (char *) &word;
return(byte[0] ? LITTLE_ENDIAN : BIG_ENDIAN);
}
รหัสนี้กำหนดค่า 0001h ให้กับจำนวนเต็ม 16 บิต ตัวชี้ถ่านจะถูกกำหนดให้ชี้ไปที่ไบต์แรก (สำคัญน้อยที่สุด) ของค่าจำนวนเต็ม หากไบต์แรกของจำนวนเต็มคือ 0x01h แสดงว่าระบบเป็น Little-Endian (0x01h นั้นอยู่ต่ำสุดหรือสำคัญน้อยที่สุด) หากเป็น 0x00h แสดงว่าระบบเป็น Big-Endian
วิธี C ++ คือการใช้บูสต์โดยที่การตรวจสอบพรีโพรเซสเซอร์และ casts ถูกแยกส่วนภายในไลบรารีที่ผ่านการทดสอบอย่างละเอียดมาก
Predef ห้องสมุด (เพิ่ม / predef.h) ตระหนักถึงสี่ชนิดที่แตกต่างกันของ endianness
ห้องสมุด Endianกำลังวางแผนที่จะส่งไปยัง C ++ มาตรฐานและการสนับสนุนที่หลากหลายของการดำเนินการกับข้อมูล endian ที่มีความอ่อนไหว
ตามที่ระบุไว้ในคำตอบข้างต้น Endianness จะเป็นส่วนหนึ่งของ c ++ 20
ถ้าคุณไม่ได้ใช้เฟรมเวิร์กที่ต่อเข้ากับโพรเซสเซอร์ PPC และ Intel คุณจะต้องทำการคอมไพล์แบบมีเงื่อนไขเนื่องจากแพลตฟอร์ม PPC และ Intel นั้นมีสถาปัตยกรรมฮาร์ดแวร์แตกต่างกันไปอย่างสิ้นเชิงท่อส่งสัญญาณและอื่น ๆ ทั้งสอง.
สำหรับการค้นหา endianness ทำต่อไปนี้:
short temp = 0x1234;
char* tempChar = (char*)&temp;
คุณจะได้รับ tempChar เป็น 0x12 หรือ 0x34 ซึ่งคุณจะรู้ว่า endianness
stdint.h
และใช้int16_t
เพื่อการพิสูจน์ในอนาคตต่อความแตกต่างในระยะสั้นบนแพลตฟอร์มอื่น
ฉันจะทำสิ่งนี้:
bool isBigEndian() {
static unsigned long x(1);
static bool result(reinterpret_cast<unsigned char*>(&x)[0] == 0);
return result;
}
ในบรรทัดเหล่านี้คุณจะได้รับฟังก์ชั่นเวลาที่มีประสิทธิภาพซึ่งทำการคำนวณเพียงครั้งเดียวเท่านั้น
ตามที่ระบุไว้ข้างต้นใช้กลวิธียูเนี่ยน
มีปัญหาเล็กน้อยกับปัญหาที่แนะนำไว้ข้างต้น แต่ที่น่าสังเกตว่าการเข้าถึงหน่วยความจำที่ไม่ได้จัดแนวนั้นช้ามากสำหรับสถาปัตยกรรมส่วนใหญ่และคอมไพเลอร์บางตัวจะไม่รู้จักภาคแสดงคงที่เช่นนั้นเว้นแต่จะจัดแนวคำ
เนื่องจากการทดสอบ endian นั้นน่าเบื่อเพียงแค่นี้ไปที่ฟังก์ชัน (เทมเพลต) ซึ่งจะพลิกอินพุต / เอาต์พุตของเลขจำนวนเต็มตามที่คุณต้องการโดยไม่คำนึงถึงสถาปัตยกรรมโฮสต์
#include <stdint.h>
#define BIG_ENDIAN 1
#define LITTLE_ENDIAN 0
template <typename T>
T endian(T w, uint32_t endian)
{
// this gets optimized out into if (endian == host_endian) return w;
union { uint64_t quad; uint32_t islittle; } t;
t.quad = 1;
if (t.islittle ^ endian) return w;
T r = 0;
// decent compilers will unroll this (gcc)
// or even convert straight into single bswap (clang)
for (int i = 0; i < sizeof(r); i++) {
r <<= 8;
r |= w & 0xff;
w >>= 8;
}
return r;
};
การใช้งาน:
ในการแปลงจาก endian ที่กำหนดให้ใช้:
host = endian(source, endian_of_source)
หากต้องการแปลงจากโฮสต์ endian เป็น endian ที่กำหนดให้ใช้:
output = endian(hostsource, endian_you_want_to_output)
โค้ดผลลัพธ์นั้นเร็วเท่ากับการเขียนชุดประกอบมือบนเสียงดังกราวบน gcc มันช้ากว่าเล็กน้อย (ไม่มีการควบคุม &, <<, >>, | สำหรับทุกไบต์) แต่ก็ยังดี
bool isBigEndian()
{
static const uint16_t m_endianCheck(0x00ff);
return ( *((uint8_t*)&m_endianCheck) == 0x0);
}
#define IS_BIGENDIAN() (*((char*) &((int){ 0x00ff })) == (0x00))
อย่าใช้union
!
C ++ ไม่อนุญาตให้พิมพ์ punning ผ่านunion
s!
การอ่านจากเขตข้อมูลร่วมที่ไม่ใช่เขตข้อมูลสุดท้ายที่เขียนถึงเป็นพฤติกรรมที่ไม่ได้กำหนด !
คอมไพเลอร์จำนวนมากสนับสนุนการทำเช่นนั้นเป็นส่วนขยาย แต่ภาษาไม่รับประกัน
ดูคำตอบนี้สำหรับรายละเอียดเพิ่มเติม:
https://stackoverflow.com/a/11996970
มีคำตอบที่ถูกต้องเพียงสองคำเท่านั้นเท่านั้น
คำตอบแรกถ้าคุณเข้าถึงระบบที่รองรับ C ++ 20
ให้ใช้std::endian
จาก<type_traits>
ส่วนหัว
(ในขณะที่เขียน, C ++ 20 ยังไม่ได้รับการปล่อยตัว แต่ถ้าบางสิ่งบางอย่างเกิดขึ้นกับstd::endian
การรวมของสิ่งนี้จะเป็นวิธีที่ต้องการทดสอบ endianness ในเวลารวบรวมจาก C ++ 20 เป็นต้นไป)
constexpr bool is_little_endian = (std::endian::native == std::endian::little);
ก่อนถึง C ++ 20 คำตอบที่ถูกต้องเพียงข้อเดียวคือเก็บจำนวนเต็มจากนั้นตรวจสอบไบต์แรกจนถึงประเภท punning
ซึ่งแตกต่างจากการใช้union
s นี้ได้รับอนุญาตอย่างชัดแจ้งโดยระบบชนิดของ C ++
สิ่งสำคัญคือต้องจำไว้ว่าstatic_cast
ควรใช้ความสะดวกในการพกพาที่เหมาะสม
เนื่องจากreinterpret_cast
มีการกำหนดการนำไปใช้งาน
หากโปรแกรมพยายามเข้าถึงค่าที่เก็บไว้ของวัตถุผ่าน glvalue นอกเหนือจากประเภทใดประเภทหนึ่งต่อไปนี้พฤติกรรมจะไม่ได้กำหนด: ... a
char
หรือunsigned char
type
enum class endianness
{
little = 0,
big = 1,
};
inline endianness get_system_endianness()
{
const int value { 0x01 };
const void * address = static_cast<const void *>(&value);
const unsigned char * least_significant_address = static_cast<const unsigned char *>(address);
return (*least_significant_address == 0x01) ? endianness::little : endianness::big;
}
inline bool is_system_little_endian()
{
const int value { 0x01 };
const void * address = static_cast<const void *>(&value);
const unsigned char * least_significant_address = static_cast<const unsigned char *>(address);
return (*least_significant_address == 0x01);
}
inline bool is_system_little_endian()
{
const int value = 0x01;
const void * address = static_cast<const void *>(&value);
const unsigned char * least_significant_address = static_cast<const unsigned char *>(address);
return (*least_significant_address == 0x01);
}
union {
int i;
char c[sizeof(int)];
} x;
x.i = 1;
if(x.c[0] == 1)
printf("little-endian\n");
else printf("big-endian\n");
นี่คือทางออกอื่น คล้ายกับโซลูชันของ Andrew Hare
ยังไม่ทดลอง แต่ในความคิดของฉันมันควรจะใช้ได้ไหม ทำให้มันเป็น 0x01 สำหรับ endian น้อยและ 0x00 สำหรับ endian ใหญ่?
bool runtimeIsLittleEndian(void)
{
volatile uint16_t i=1;
return ((uint8_t*)&i)[0]==0x01;//0x01=little, 0x00=big
}
ประกาศ:
เวลาในการรวบรวม, ไม่ใช่มาโคร, โซลูชัน C ++ 11 constexpr:
union {
uint16_t s;
unsigned char c[2];
} constexpr static d {1};
constexpr bool is_little_endian() {
return d.c[0] == 1;
}
คุณยังสามารถทำสิ่งนี้ผ่านตัวประมวลผลล่วงหน้าโดยใช้ไฟล์ส่วนหัวบูสต์ซึ่งพบได้ในบูสต์ endian
เว้นแต่ว่าส่วนหัวของ endian นั้นเป็น GCC เท่านั้น แต่จะให้มาโครที่คุณสามารถใช้ได้
#include "endian.h"
...
if (__BYTE_ORDER == __LITTLE_ENDIAN) { ... }
else if (__BYTE_ORDER == __BIG_ENDIAN) { ... }
else { throw std::runtime_error("Sorry, this version does not support PDP Endian!");
...
__BYTE_ORDER__
, __ORDER_LITTLE_ENDIAN__
และ__ORDER_BIG_ENDIAN__
?
หากคุณไม่ต้องการการรวบรวมตามเงื่อนไขคุณสามารถเขียนโค้ดอิสระของ endian ได้ นี่คือตัวอย่าง (นำมาจากRob Pike ):
การอ่านจำนวนเต็มเก็บไว้ใน little-endian บนดิสก์ในลักษณะอิสระ endian:
i = (data[0]<<0) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
รหัสเดียวกันพยายามพิจารณา endianness ของเครื่อง:
i = *((int*)data);
#ifdef BIG_ENDIAN
/* swap the bytes */
i = ((i&0xFF)<<24) | (((i>>8)&0xFF)<<16) | (((i>>16)&0xFF)<<8) | (((i>>24)&0xFF)<<0);
#endif
int i=1;
char *c=(char*)&i;
bool littleendian=c;
แล้วเรื่องนี้ล่ะ
#include <cstdio>
int main()
{
unsigned int n = 1;
char *p = 0;
p = (char*)&n;
if (*p == 1)
std::printf("Little Endian\n");
else
if (*(p + sizeof(int) - 1) == 1)
std::printf("Big Endian\n");
else
std::printf("What the crap?\n");
return 0;
}
นี่คือเวอร์ชั่น C อีกอัน มันกำหนดแมโครที่เรียกว่าwicked_cast()
สำหรับประเภทอินไลน์เล่นสำนวนผ่าน C99 ตัวอักษรยูเนี่ยนและไม่ได้มาตรฐาน__typeof__
ผู้ประกอบการ
#include <limits.h>
#if UCHAR_MAX == UINT_MAX
#error endianness irrelevant as sizeof(int) == 1
#endif
#define wicked_cast(TYPE, VALUE) \
(((union { __typeof__(VALUE) src; TYPE dest; }){ .src = VALUE }).dest)
_Bool is_little_endian(void)
{
return wicked_cast(unsigned char, 1u);
}
ถ้าจำนวนเต็มเป็นค่าไบต์เดียวความไม่มีจุดมุ่งหมายและข้อผิดพลาดในการคอมไพล์เวลาจะถูกสร้างขึ้น
คอมไพเลอร์ทาง C (ที่ทุกคนอย่างน้อยฉันรู้) ทำงาน endianness มีจะต้องตัดสินใจที่รวบรวมเวลา แม้แต่โปรเซสเซอร์ biendian (เช่น ARM och MIPS) คุณต้องเลือก endianness ในเวลารวบรวม นอกจากนี้ endianness ถูกกำหนดในรูปแบบไฟล์ทั่วไปทั้งหมดสำหรับไฟล์เรียกทำงาน (เช่น ELF) แม้ว่ามันจะเป็นไปได้ที่จะสร้างไบนารีไบน์ของรหัส biandian (สำหรับเซิร์ฟเวอร์ ARM บางอย่างอาจจะใช้ประโยชน์จาก?) มันอาจจะต้องทำในการชุมนุม
ดังที่ Coriiander ระบุไว้ส่วนใหญ่ (ถ้าไม่ใช่ทั้งหมด) ของรหัสเหล่านี้ที่นี่จะได้รับการปรับปรุงให้ดีที่สุดเมื่อถึงเวลารวบรวมดังนั้นไบนารีที่สร้างขึ้นจะไม่ตรวจสอบ "endianness" ในเวลาทำงาน
มันถูกตั้งข้อสังเกตว่าการปฏิบัติการที่กำหนดไม่ควรรันในคำสั่งไบต์ที่แตกต่างกันสองคำสั่ง แต่ฉันไม่รู้ว่ามันเป็นเช่นนั้นเสมอและดูเหมือนว่าแฮ็คจะให้ฉันตรวจสอบเวลารวบรวม ดังนั้นฉันเขียนฟังก์ชั่นนี้:
#include <stdint.h>
int* _BE = 0;
int is_big_endian() {
if (_BE == 0) {
uint16_t* teste = (uint16_t*)malloc(4);
*teste = (*teste & 0x01FE) | 0x0100;
uint8_t teste2 = ((uint8_t*) teste)[0];
free(teste);
_BE = (int*)malloc(sizeof(int));
*_BE = (0x01 == teste2);
}
return *_BE;
}
MinGW ไม่สามารถปรับรหัสนี้ให้เหมาะสมแม้ว่าจะเพิ่มประสิทธิภาพรหัสอื่นที่นี่ ฉันเชื่อว่าเป็นเพราะฉันปล่อยให้ค่า "สุ่ม" ที่ได้รับการจัดสรรในหน่วยความจำไบต์ที่มีขนาดเล็กตามที่มันเป็น (อย่างน้อย 7 ของบิต) ดังนั้นคอมไพเลอร์ไม่สามารถรู้ว่าค่าสุ่มคืออะไรและไม่ปรับให้เหมาะสม ฟังก์ชั่นออกไป
ฉันได้เขียนโค้ดฟังก์ชันเพื่อให้การตรวจสอบทำได้เพียงครั้งเดียวและค่าส่งคืนจะถูกเก็บไว้สำหรับการทดสอบครั้งต่อไป
0x7FE
? ทำไมต้องใช้งานmalloc()
เลย? ที่สิ้นเปลือง และ_BE
เป็นหน่วยความจำรั่ว (แม้ว่าเล็ก) และสภาพการแข่งขันที่รอให้เกิดขึ้นประโยชน์ของการแคชผลลัพธ์แบบไดนามิกไม่คุ้มกับปัญหา ฉันจะทำสิ่งนี้มากกว่านี้แทน: ใช้งานstatic const uint16_t teste = 1; int is_little_endian() { return (0x01 == ((uint8_t*)&teste)[0]); } int is_big_endian() { return (0x01 == ((uint8_t*)&teste)[1]); }
ง่ายและมีประสิทธิภาพ
volatile
หรือ#pragma
ฯลฯ
ในขณะที่ไม่มีวิธีที่รวดเร็วและเป็นมาตรฐานในการพิจารณามันจะเอาท์พุทมัน:
#include <stdio.h>
int main()
{
unsigned int i = 1;
char *c = (char*)&i;
if (*c)
printf("Little endian");
else
printf("Big endian");
getchar();
return 0;
}
ดูEndianness - ภาพประกอบรหัส C-Level
// assuming target architecture is 32-bit = 4-Bytes
enum ENDIANNESS{ LITTLEENDIAN , BIGENDIAN , UNHANDLE };
ENDIANNESS CheckArchEndianalityV1( void )
{
int Endian = 0x00000001; // assuming target architecture is 32-bit
// as Endian = 0x00000001 so MSB (Most Significant Byte) = 0x00 and LSB (Least Significant Byte) = 0x01
// casting down to a single byte value LSB discarding higher bytes
return (*(char *) &Endian == 0x01) ? LITTLEENDIAN : BIGENDIAN;
}
ฉันกำลังอ่านหนังสือ: ระบบคอมพิวเตอร์: มุมมองของโปรแกรมเมอร์และมีปัญหาในการพิจารณาว่า endian ตัวนี้คืออะไรโดยโปรแกรม C
ฉันใช้คุณสมบัติของตัวชี้เพื่อทำดังต่อไปนี้:
#include <stdio.h>
int main(void){
int i=1;
unsigned char* ii = &i;
printf("This computer is %s endian.\n", ((ii[0]==1) ? "little" : "big"));
return 0;
}
ในฐานะที่เป็นintใช้เวลา 4 ไบต์และถ่านใช้เวลาเพียง 1 ไบต์ เราสามารถใช้ตัวชี้ถ่านให้ชี้ไปที่intมีมูลค่า 1 ดังนั้นหากคอมพิวเตอร์ที่เป็น endian เล็ก ๆ น้อย ๆถ่านที่ตัวชี้ถ่านจุดที่จะต้องอยู่กับมูลค่า 1 มิฉะนั้นค่าที่ควรจะเป็น 0