SWAPマクロ改良
主な変更点
- コメント整備
- 入れ替えるオブジェクトのサイズチェックを行い、サイズが異なる場合、入れ替えを行わないに修正。
- サンプルドライバ結果表示の改善
- 識別子が衝突しにくいように、一時変数名、型名を長くした。
#include <stdio.h> /* オブジェクトa, bの値を入れ替えるマクロ関数 */ /* note: a, bは代入可能なオブジェクトを渡すこと */ /* sizeof a, sizeof bが異なる場合何もしない。 */ /* a, bに識別子swapMacroTmpを与えると誤動作する。 */ /* 既存コードにstruct TTmpSWAP_MACROがあるとコンパイルエラー */ #define SWAP(a, b) do{ \ struct TTmpSWAP_MACRO { \ char buf[sizeof(a)]; \ } swapMacroTmp; \ \ if (sizeof(a) == sizeof(b)) { \ swapMacroTmp = *((struct TTmpSWAP_MACRO *)&(a)); \ *((struct TTmpSWAP_MACRO *)&(a)) = *((struct TTmpSWAP_MACRO *)&(b)); \ *((struct TTmpSWAP_MACRO *)&(b)) = swapMacroTmp; \ } \ }while(0) /* 動作確認用構造体 */ /* printfで表示しやすいように4バイトに合わせただけ */ typedef struct THoge { char a; char b; char c; char d; } THoge; /* XOR版swap関数 */ void swap(int *a, int *b) { *a = *a ^ *b; *b = *b ^ *a; *a = *a ^ *b; } /* 使い方サンプルドライバ */ int main(void) { int iA = 0xfedcba98, iB = 0x12345678; float fA = 0.0, fB = 3.14; int *pA = &iA, *pB = &iB; THoge tA = {1, 2, 3, 4}, tB = {9, 8, 7, 6}; char strA[] = "123", strB[] = "abc"; /* intの入れ替え */ printf("\n ==== swap int ====\n"); printf("before: %08x, %08x\n", iA, iB); SWAP(iA, iB); printf("after: %08x, %08x\n", iA, iB); /* floatの入れ替え */ printf("\n ==== swap float ====\n"); printf("before: %08x, %08x\n", *((int *)&fA), *((int *)&fB)); SWAP(fA, fB); printf("after: %08x, %08x\n", *((int *)&fA), *((int *)&fB)); /* ポインタの入れ替え */ printf("\n ==== swap pointer ====\n"); printf("before: %p, %p\n", pA, pB); SWAP(pA, pB); printf("after: %p, %p\n", pA, pB); /* 構造体の入れ替え */ printf("\n ==== swap struct ====\n"); printf("before: %08x, %08x\n", *((int *)&tA), *((int *)&tB)); SWAP(tA, tB); printf("after: %08x, %08x\n", *((int *)&tA), *((int *)&tB)); /* 配列の入れ替え */ printf("\n ==== swap array ====\n"); printf("before: %08x, %08x\n", *((int *)strA), *((int *)strB)); SWAP(strA, strB); printf("after: %08x, %08x\n", *((int *)strA), *((int *)strB)); /* intの入れ替え同じオブジェクト */ printf("\n ==== swap int(same object) ====\n"); printf("before: %08x, %08x\n", iA, iA); SWAP(iA, iA); printf("after: %08x, %08x\n", iA, iA); /* intの入れ替え同じオブジェクトXOR版 */ printf("\n ==== (XOR ver)swap int(same object) ====\n"); printf("before: %08x, %08x\n", iA, iA); swap(&iA, &iA); /* 同じオブジェクトを渡すと値が失われる。 */ printf("after: %08x, %08x\n", iA, iA); return 0; }
実行結果
$ ./main ==== swap int ==== before: fedcba98, 12345678 after: 12345678, fedcba98 ==== swap float ==== before: 00000000, 4048f5c3 after: 4048f5c3, 00000000 ==== swap pointer ==== before: 0x22cd64, 0x22cd60 after: 0x22cd60, 0x22cd64 ==== swap struct ==== before: 04030201, 06070809 after: 06070809, 04030201 ==== swap array ==== before: 00333231, 00636261 after: 00636261, 00333231 ==== swap int(same object) ==== before: 12345678, 12345678 after: 12345678, 12345678 ==== (XOR ver)swap int(same object) ==== before: 12345678, 12345678 after: 00000000, 00000000