2017-03-23 4 views
1

ポインタが整列した境界を指していることをgccに示唆することができるかどうか疑問に思っています。私が機能している場合:cポインタの整列

void foo (void * pBuf) { 
    uint64_t *pAligned = pBuf; 
    pAligned = ((pBuf + 7) & ~0x7); 
    var = *pAligned; // I want this to be aligned 64 bit access 
} 

をそして私はPBUFは64ビット整列されていることを知っている、64ビット境界にpAlignedポイントというのgccを伝えるためにどのような方法はありますか?私が行う場合:

uint64_t *pAligned __attribute__((aligned(16))); 

私は、ポインタのアドレスは64ビット整列されていることを意味信じているが、それは何それが指すが整列されたコンパイラを教えてくれないので、コンパイラはそう言うだろうここではアラインされていないフェッチを行います。私が大きな配列をループしていると、これが遅くなる可能性があります。

答えて

2

GCCにアライメントを通知する方法はいくつかあります。

int foo() { 
    int __attribute__((aligned(16))) *p; 
    return (unsigned long long)p & 3; 
} 

それとも、(比較的新しい)組み込み使用することができます:両方の変形が原因アライメントにreturn 0に最適化

int bar(int *p) { 
    int *pa = __builtin_assume_aligned(p, 16); 
    return (unsigned long long)pa & 3; 
} 

まず、あなたではなく、ポインタよりも、指示先に属性を揃える添付することができます。

typedef int __attribute__((aligned(16))) *aligned_ptr; 

int baz(aligned_ptr p) { 
    return (unsigned long long)p & 3; 
} 
と、この1でもドキュメント suggest the oppositeかかわらず、どちらか

typedef int aligned_int __attribute__((aligned (16))); 

int braz(aligned_int *p) { 
    return (unsigned long long)p & 3; 
} 

ない:

残念ながら、次は動作するようには思えません。

+0

ここで言及したように、最初の例では明らかなように聞こえます...どのように私はそれを逃したかわかりません。ありがとう。私はtypedefがうまくいかないことに驚いています。私のコードの他の部分では便利かもしれません。 – blackghost

+0

@ John GCCでもドキュメントをサポートしていますが(https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#Common-Type-Attributes)、ドキュメントは入手できませんでした私のGCC 5.4で動作するようになりました。 – yugr

+0

最後の2つのケースでは、パラメータを整列しようとしていて、コンパイル時にパラメータが分からないと仮定しています。したがって、gccはパラメータを強制的に整列させることができません。誰かが0xabcd0001をスタックにプッシュした場合、ポインタが実際には奇妙になることがあるかもしれませんが、それ以外の場合、アライメントされていないパラメータを渡そうとすると警告を生成する可能性があります。しかし、内部のコードは、アライメントの前提となる可能性があります。メモリアクセスは、アライメントされていない例外を引き起こす可能性があります。 – blackghost