void qsort (void *a, size_t n, size_t es, int (*compare)(const void *, const void *)
ここで、aは配列アドレスの開始、nは配列のサイズ、esは配列要素のサイズです。
理解できないCのqsortのソースコードを読みました。コードは次のとおりです。
#define SWAPINT(a,es) swaptype = ((char*)a- (char*)0 % sizeof(long) || \
es % sizeof(long) ? 2: es == sizeof(long)? 0 : 1
私はこのマクロを次のように解釈します。
if(((char*)a- (char*)0)% sizeof(long))==1 || es % sizeof(long)==1)
swaptype = 2;
else if(es== sizeof(long))
swaptype = 0;
else
swaptype = 1;
しかし、なぜ型変換が実装されているのかわかりません(char *)a。
そして、この線の意味は何ですか?
(char*)a- (char*)0)% sizeof(long)==1
そのコードを見つけたところはどこでも、おそらくそれを間違ってコピーしたでしょう。libutil
Canuから非常によく似たコードを見つけました:
c.swaptype = ((char *)a - (char *)0) % sizeof(long) || \
es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
このコードは、FreeBSDのlibcからコピーされた可能性があります(著作権ライセンスの条件に違反しているため)。
//__FBSDID("$FreeBSD: src/lib/libc/stdlib/qsort.c,v 1.12 2002/09/10 02:04:49 wollman Exp $");
ですから、* BSDlibcの実装から得たと思います。実際、FreeBSDのクイックソート実装にはSWAPINIT
マクロが含まれています(ではありませんSWAPINT
)。
#define SWAPINIT(TYPE, a, es) swaptype_ ## TYPE = \
((char *)a - (char *)0) % sizeof(TYPE) || \
es % sizeof(TYPE) ? 2 : es == sizeof(TYPE) ? 0 : 1;
解析後、上記のコードはほぼ同じであることがわかります。
condition_one = ((char *)a - (char *)0) % sizeof(long);
condition_two = es % sizeof(long);
condition_three = es == sizeof(long);
c.swaptype = (condition_one || condition_two) ? 2 : condition_three ? 0 : 1;
なおcondition_two
条件として、ではないと同じes % sizeof(long) == 1
ではなくes % sizeof(long) != 0
。それを除けば、あなたの翻訳は正しかった。
これらの条件の意図は次のように思われます。
condition_one
が整列されていないtrue
場合a
ですlong
。condition_two
あるtrue
ときes
の倍数ではありませんlong
。condition_three
あるtrue
ときes
、正確ですlong
。結果として、
swaptype == 2
交換について賢くするための要素についての十分な保証がない場合です。swaptype == 1
long
境界に沿って整列された要素を持つ配列を対象としています(注:ただし、必ずしもlongとして整列されている必要はありません!)。swaptype == 0
前の説明に一致し、long
サイズも同じ要素を持つ配列を対象としています。ので、この場合には、明示的な型変換は、あるa
タイプ有するvoid*
、型演算が定義されていたために。ただし、これも((char *)a - (char *)0)
未定義であることに注意してください。
2つのポインターが減算される場合、両方が同じ配列オブジェクトの要素を指すか、配列オブジェクトの最後の要素を1つ過ぎたものを指します。結果は、2つの配列要素の添え字の違いです。
(C11ドラフトN1570、セクション6.5.6、93および94ページの条項9。)
C11では正確に記述されていませんが、nullポインターは、が指すオブジェクトと同じ配列の一部ではないa
ため、ポインター演算の基本規則に違反しているため、動作は定義されていません。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加