2012-04-07 5 views
7

私は教科書を見ていますが、そこにあるコードについては少し混乱しています。一部では、彼らは次のようにポインタ演算を実行している:void *とchar *ポインタの算術

void* bp; 
... 
bp = (void*)((char*)(bp)+16); 
... 

が、後に、彼らは次のようにします。

void* bp; 
... 
bp = bp+16; 
... 

彼らは二つの異なるものでなければなりませんような気がしますが、彼らが扱っていますそれは同じことが好きです。 たとえば、あなたが(例えば整数配列のための)配列アクセスを行うとしたら、あなたはこの場合は、次の

int* a = malloc(n*sizeof(int)); 
... 
q = *(a+1); 
... 

を行うだろう、私は次のにアクセスしていない、ので、私はこのように感じます整数配列の4バイトで、次のバイトではありませんか? 同様に、もし私がvoid * aを持っていれば、次の4バイトは*(a + 1)でなければならないと感じます... それともそうではありませんか? ありがとうございます。

+0

この2番目の例はコンパイルすべきではありません。 –

+1

@OliCharlesworth:準拠モードでコンパイルすると、コンパイルされません(または少なくとも警告をトリガーします)。 gccはデフォルトでは準拠しておらず、拡張として 'void *'算術を実装しています。 –

答えて

11

スリップアップです。 void *の算術演算は標準では定義されていませんが、一部のコンパイラでは算術演算のためにchar *と同じように動作します。 2番目は正式には有効ではありませんが、おそらく(悪い)習慣から抜け出しました。

+0

したがって、次の16バイトにアクセスする適切な方法は、最初にchar *にキャストして16を追加することでしょうか?笑、すぐに良い量のコードを変更する必要があります。ああ、私は少し間違って最初のものをコピーした、私は小さな変更を加えたが、私はそれが私の質問に違いをもたらすとは思わない。 – de1337ed

+0

また、 'uint64_t *'にキャストして2を加えることもできます;)はい、移植可能な方法は、既知のサイズの型へのポインタにキャストし、それを計算することです。あなたが移植性を必要とせず、コンパイラが 'void *'算術が特定の方法で動作することを文書化しているなら、それを使うことができます。もちろん、ある時点で別のコンパイラに移植する必要があります... –

関連する問題