ฉันเพิ่งเขียนแมโครเพื่อทำสิ่งนี้ใน C แต่มันใช้ได้ใน C ++:
#define REVERSE_BYTES(...) do for(size_t REVERSE_BYTES=0; REVERSE_BYTES<sizeof(__VA_ARGS__)>>1; ++REVERSE_BYTES)\
((unsigned char*)&(__VA_ARGS__))[REVERSE_BYTES] ^= ((unsigned char*)&(__VA_ARGS__))[sizeof(__VA_ARGS__)-1-REVERSE_BYTES],\
((unsigned char*)&(__VA_ARGS__))[sizeof(__VA_ARGS__)-1-REVERSE_BYTES] ^= ((unsigned char*)&(__VA_ARGS__))[REVERSE_BYTES],\
((unsigned char*)&(__VA_ARGS__))[REVERSE_BYTES] ^= ((unsigned char*)&(__VA_ARGS__))[sizeof(__VA_ARGS__)-1-REVERSE_BYTES];\
while(0)
ยอมรับประเภทใดก็ได้และกลับไบต์ในอาร์กิวเมนต์ที่ผ่าน ตัวอย่างประเพณี:
int main(){
unsigned long long x = 0xABCDEF0123456789;
printf("Before: %llX\n",x);
REVERSE_BYTES(x);
printf("After : %llX\n",x);
char c[7]="nametag";
printf("Before: %c%c%c%c%c%c%c\n",c[0],c[1],c[2],c[3],c[4],c[5],c[6]);
REVERSE_BYTES(c);
printf("After : %c%c%c%c%c%c%c\n",c[0],c[1],c[2],c[3],c[4],c[5],c[6]);
}
สิ่งที่พิมพ์:
Before: ABCDEF0123456789
After : 8967452301EFCDAB
Before: nametag
After : gateman
ด้านบนเป็นแบบคัดลอก / วางได้อย่างสมบูรณ์แบบ แต่มีหลายอย่างเกิดขึ้นที่นี่ดังนั้นฉันจะทำลายวิธีการทำงานทีละชิ้น:
สิ่งแรกที่น่าสังเกตคือแมโครทั้งหมดถูกห่อหุ้มด้วยdo while(0)
บล็อก นี่เป็นสำนวนทั่วไปที่อนุญาตให้ใช้เครื่องหมายอัฒภาคปกติหลังจากแมโคร
ถัดไปคือการใช้ตัวแปรที่มีชื่อREVERSE_BYTES
เป็นตัวfor
นับลูป ชื่อของแมโครนั้นถูกใช้เป็นชื่อตัวแปรเพื่อให้แน่ใจว่าจะไม่ขัดแย้งกับสัญลักษณ์อื่นใดที่อาจอยู่ในขอบเขตที่ใดก็ตามที่มีการใช้งานแมโคร เนื่องจากมีการใช้ชื่อภายในส่วนขยายของแมโครจึงไม่ถูกขยายอีกเมื่อใช้เป็นชื่อตัวแปรที่นี่
ภายในfor
ลูปมีสองไบต์ที่ถูกอ้างอิงและXOR สลับกัน (ดังนั้นชื่อตัวแปรชั่วคราวไม่จำเป็น):
((unsigned char*)&(__VA_ARGS__))[REVERSE_BYTES]
((unsigned char*)&(__VA_ARGS__))[sizeof(__VA_ARGS__)-1-REVERSE_BYTES]
__VA_ARGS__
แสดงถึงสิ่งใดก็ตามที่มอบให้กับแมโครและใช้เพื่อเพิ่มความยืดหยุ่นของสิ่งที่อาจถูกส่งผ่านเข้ามา (แม้ว่าจะไม่มากก็ตาม) ที่อยู่ของอาร์กิวเมนต์นี้จะถูกนำมาใช้แล้วโยนไปที่unsigned char
ตัวชี้เพื่ออนุญาตให้สลับไบต์ผ่าน[]
การห้อยแถวลำดับ
จุดแปลกประหลาดสุดท้ายคือการขาดการ{}
จัดฟัน พวกเขาไม่จำเป็นเพราะทุกขั้นตอนในการแลกเปลี่ยนแต่ละครั้งจะเข้าร่วมกับผู้ประกอบการคอมม่าทำให้พวกเขาหนึ่งคำสั่ง
ในที่สุดมันก็น่าสังเกตว่านี่ไม่ใช่วิธีที่ดีถ้าความเร็วเป็นสิ่งที่สำคัญที่สุด หากนี่เป็นปัจจัยสำคัญมาโครเฉพาะบางประเภทหรือคำสั่งเฉพาะแพลตฟอร์มที่อ้างถึงในคำตอบอื่นอาจเป็นตัวเลือกที่ดีกว่า อย่างไรก็ตามวิธีนี้สามารถพกพาได้ทุกประเภทแพลตฟอร์มหลักทั้งหมดและทั้งภาษา C และ C ++