2017-11-08 19 views
-1

私はポインタ算術で遊んでいて、ポインタの減算と比較に関するC標準の2つのルールに遭遇しました。ポインタの減算と比較ルールの混乱

ルール1:2つのポインタを減算する場合、どちらも同じ配列オブジェクトの要素を指すか、配列オブジェクトの最後の要素を1つだけ指す必要があります(C標準、6.5.6)。結果は2つの配列要素の下付き文字の違いになります。それ以外の場合、操作は未定義の動作です(48)。

ルール2:同様に、関係演算子<を使用するポインタを比較すると、< =、> =、および>は、相互の相対的なポインタの位置を示します。同じ集合体または共用体を指していない(同じ配列オブジェクトを超えている)ポインタは、関係演算子(6.5.8)を使用して比較されます。それ以外の場合、操作は未定義の動作です(53)。

同じ配列を参照しないポインタを減算または比較することは、未定義の動作です。

質問1:上記のルール1のとおり、動作は未定義ですが、プログラムはアドレスを出力として出力します。アドレスを含む変数を逆参照しようとすると、プログラムがクラッシュします。存在する住所はどうしてありますか?住所が指す値は存在しません。

質問2:2つの異なる配列を参照する2つのポインタを比較演算子を使って比較すると、定義されていない動作ですが、プログラムはクラッシュしますが、結果は出力に終わりますか?そんなことがあるものか?

誰かがこのルールの混乱に関してお手伝いできますか?私は以下のコードを掲載している2つのポインタを減算

#include <stdio.h> 

int main() 
{ 
char *pointer_1; 
char *pointer_2; 
char *difference; 
int counter=0; 

char string[20]={"Pointer Arithmetic"}; 
char str[30]={"Substraction and Comparison"}; 

pointer_1=string; 
pointer_2=str; 

difference=(char *)(pointer_2-pointer_1); 
printf("%p\n",difference); Address exists 

/*printf("%c\n",difference);*/ Dereferencing leads to program crash  

while(pointer_1>pointer_2) Is one is allowed to use relational operators on 
           pointers which point to two different arrays? 
    {        
    { 
     counter++; 
     pointer_2++; 
    } 
    } 

    printf("%d",counter); 

} 
+3

未定義の動作!=クラッシュする必要があります。それは「正しく」働くことを含む何でもすることができます。 – HolyBlackCat

+0

ポインタの結果を 'int'に引く。だから 'difference =(char *)(pointer_2-pointer_1);'は意味をなさない。 –

+0

2つのアドレスの違いは、それ自体がアドレスではありません。明確に述べられているように、それは「下付き文字の違い」です。 %pを使用しても1つにならないので、printfはプログラムをクラッシュさせる義務がありません。 –

答えて

1

ポインタ(「アドレス」)をもたらさない、それは、これらのポインタとの間の「距離」である整数になります。これは、ポインターが両方とも同じ配列を指している場合にのみ意味をなさない。同様に、ポインタを比較することは、それらが同じ配列内にある場合にのみ意味を持ちます。

意味がない場合、結果は定義されていません。つまり、プログラムが失敗したり、クラッシュしたり、エラーが発生することはありません。それは何かが起こる可能性があることを意味し、あなたは不平を言う権利がありません。

0

未定義の動作はテストできません。その結果は、まったく定義されていないためです。

予測結果の取得、クラッシュ、予期しない結果の取得、またはcausing time travelなどの結果が考えられます。

この場合、一般的なデスクトップコンピュータでは、2つの無関係なポインタpointer_1>pointer_2を比較すると、2つのポインタに格納されているアドレスが比較される可能性があります。だから、それは "動く"。

セグメント化されたメモリを持つコンピュータでは、286のように、メモリアドレスはsegment:offsetのペアで構成されます。 2つのセグメント値を比較すると、どれが最高のメモリアドレスを表すかについては何も言わない。それは、実アドレスアドレスを含むセグメント記述子テーブルへの単なるインデックスである。

したがって、配列が2つの異なるセグメントにある場合(非常に一般的ですが、セグメントが小さいため)、順序のポインタを比較することはあまり意味がなく、それらを減算することは機能しませんでした。

時にはが動作しないので、言語標準ではそうすることはできません。