『Cとポインタ』(メモ4)を読み直す


1.シフト動作基準は、シンボル値なしで実行されるすべてのシフト動作が論理シフトであることを示しているが、シンボル値がある場合、論理シフトを採用するかシフト動作を採用するかはコンパイラに依存し、テストプログラムテストを作成することができる.2.ビットオペレータAND(AND),OR(または),XOR(OR).例1:指定したビットを1:value=value|1</* */ void swap(int *a,int *b) { *a = *a ^ *b;// 1 *b = *a ^ *b;// 2 *a = *a ^ *b;// 3 }
上の詳細を説明します.まず、異和の定義は、2つのビットが異なり、結果は1で、2つのビットが同じで、結果は0です.だから、a^a=0、a^0=a.*aに格納されている値がA、*bに格納されている値がBであると仮定するので、式1の演算後、*aに格納されている値はA^Bである.式2を解くには*a=A^Bが必要であるため、式2は*b=A^B^Bに等価である.2つの同一の数異または値が0であるため、B^B=0であり、また任意の数と0異または結果がこの数そのものであるため、A^0=Aであり、*bはAに格納される.式3を見てください.注意このとき*aが格納されているのかA^Bなのか、*bが格納されているのはすでにAなので、式3は*a=A^B^Aに等しい.結果は同じで、自然とBです.これにより、*a*bが中間変数を介さずに値を交換することが実現される.
3.複合代入子a+=expression;//expressionをaに加えると、a=a+(expression)に相当します.2つのコードは、現代のコンパイラによって最適化されても大きな違いはありませんが、次の文です.
a[2 * (y - 6*f(x))] = a[2 * (y - 6*f(x))] + 1;// 1
a[2 * (y - 6*f(x))] += 1;// 2

関数fに副作用がなければ、彼らの効果は同等である.しかし、方式1で配列の下付き文字を選択するために使用される式は2回書かなければならず、コンパイラは関数fが副作用を有するかどうかを知らないため、下付き文字式を2回計算しなければならないが、第2の形式は効率が高い.下付き文字式は1回しか計算されないからである.
4.単一オペレータ(1つのオペランドのみを受け入れるオペレータ):オペランドに対して論理反転を実行します.オペランドが真の場合、結果は偽であり、オペランドが偽の場合、結果は真である.実は!整数、0または1を生成します.
~:整数型タイプの操作数を補完操作し,操作数のすべてが1であったビットが0になり,すべてが0であったビットが1になる.
&:そのオペランドを生成するアドレス.次の例を示します.
int a,*b;
b = &a;

&オペレータは変数aのアドレスを取得し、ポインタ変数bに値を付与する.
*:間接アクセスオペレータ.ポインタが指す変数にアクセスするために、ポインタとともに使用されます.上記の例のように、bの値は変数aのアドレスであるが、*bの値は変数aの値である.
sizeof:このオペレータは、バイト単位でオペランドのタイプ長を判断するために使用されます.そのオペランドは、式であってもよいし、両側に括弧を付けたタイプ名であってもよい.sizeof(int)sizeof a(この式はsizeof(a)に等しい)最初の式が返すバイト数は、マシンに依存し、2番目の式はaという変数が占めるバイト数を返す.定義上、文字変数の長さは1バイトです.なお、sizeofのオペランドが配列名である場合、配列の長さはバイト単位で返されます.式の長さを判断しても式は評価されないためsizeof(a=b+1)はaに値を与えない.
(タイプ)オペレータは、強制タイプ変換と呼ばれます.優先度が高いため、式の最初の項目のタイプのみが変更されます.
++と–:両方の使用方法、接頭辞、接尾辞で、左の値にのみ使用できます.接頭辞と接尾辞形式の付加価値オペレータは変数値のコピーをコピーしますが、接頭辞オペレータはコピーする前に変数の値を増やし、接尾辞オペレータは変数の値をコピーしてから変数の値を増やします.これらのオペレータの結果は、変更された変数ではなく、変数値のコピーであるため、++a=10;++aの結果はa値のコピーであり,変数ではなく,1つの値に値を割り当てるのは当然誤りである.次の例を見てみましょう.
int a,b,c,c;
a=b=10;//a b 10
c=++a;//++ a, a, a 11,c 11
d=b++;//++ b, 10, b, b 11, d , 10

6.リレーショナルオペレータここでは==
if(a == 0)// 1
{}
if(0 == a)// 2
{}

どちらの判断も正しいが、方式1が間違っている場合はif(a=0)と判断文が永遠に成立し、BUGを招くことが多く、発見しやすいとは限らない.2つ目の書き方は、「==」を「=」と書いたかどうかをコンパイラにチェックしてもらうことができる.定数に値を与えるのは間違っているので、コンパイラはチェックすることができる.
7.算術変換int a=5000;int b = 25; long c = a*b; なお、a*bは整形で計算されており、32ビットのマシンで動作すれば間違いないが、16ビットのマシンでオーバーフローが発生するため、cは誤った値に初期化される.解決策は、乗算を実行する前に、そのうちの1つまたは2つをlongに変換することである.