최근에 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 ++ 언어 모두에 이식 가능합니다.