アカウント名:
パスワード:
pointer==NULL; pointer変数の参照しているアドレスがゼロ番地です。 pointer=malloc(10);などせずに*pointer='a'などとすると、ゼロ番地への書き込みになるため、普通のアプリケーションはセグメンテーションフォルトで落ちます。
pointer!=NULL && *pointer=='\0' pointer変数の参照しているアドレスはたぶん普通にデータをストアできる場所かもしれません。 しかし文字列としてみた場合、このポインタがさしている先の文字列の長さはゼロですので、strlen(pointer)==0が成り立ちます。 ただし、pointerのさしている先が本当にデータセグメントであるという保証はないので、ゼロ番地以外であってもおかしな場所をさしていれば、代入式は失敗し、セグメンテーションフォルトなどをやはり引き起こします。
あとはC言語での評価順序の問題がありますね。 f(a(x), b(y), c(z)); という関数呼び出しがあったとき、a(x), b(y), c(z)の各関数はどの順で呼ばれるのかCの仕様ではきまっていないのです。 つまりb(y)が呼ばれたあとにc(z)がよばれ、最後にa(x)がよばれ、引数が揃ったところでf()が呼ばれるかもしれません。もしかしたら自動並列コンパイラがa(), b(),c()が互いに素で並列に実行しても問題ないと判断したら並列に処理してしまうかもしれないのです。
ところが、 (a || b)と(a && b)と(a ,b))(カンマ演算子)と(a ? b : c)(三項演算子)では必ずaが先に評価され、その結果次第によってb, cが呼ばれるときまっています。 # ただし、ビット演算子である(a|b)や(a&b)の順序は不定。
このへんを理解していないと、
if(pointer==NULL||*pointer='\0') ;
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
犯人はmoriwaka -- Anonymous Coward
ほとんど無い (スコア:1, すばらしい洞察)
・インデントはTabで。
・テクニックに走らず、誰が見てもわかりそうな構文で。
・できるだけ省略しないで書いて。
命名規則とかは、今の会社では無いですね。
Re: (スコア:1, 興味深い)
ここで紛糾するんだよね。C言語限定だと
if(pointer==NULL||*pointer='\0')って書いて「NULLポインタを参照するなよ」っていわれるとか。
「for(p = buf; *p; ++p)」って書いて「for(i = 0; i < strlen(buf); i++)にしろ」と怒られるとか。
「sprintf(buf, "%*d", digits, num);」って書いて訳分からんと怒られるとか。
3項演算子のことは知りません。
Re:ほとんど無い (スコア:1)
> if(pointer==NULL||*pointer='\0')って書いて「NULLポインタを参照するなよ」っていわれる
これって「NULLポインタ」と言うやつになるのでしょうか?
いまだC言語勉強中の理解では「pointer変数の中身がNULL」もしくは「*pointerに'\0'を代入」
と言うだけで、「NULLポインタ」というのとは違うように思うのですが…
#仮に[*pointer == '\0']であっても「*pointerを参照したら'\0'(NULL文字)が入っている」のような気がするし…
#他の2つはなんとか理解できました。
理解が間違っているようであればご指導ください。
え〜ぞう
#北斗神拳使いのroot三連星
Re:ほとんど無い (スコア:1, 参考になる)
pointer==NULL;
pointer変数の参照しているアドレスがゼロ番地です。
pointer=malloc(10);などせずに*pointer='a'などとすると、ゼロ番地への書き込みになるため、普通のアプリケーションはセグメンテーションフォルトで落ちます。
pointer!=NULL && *pointer=='\0'
pointer変数の参照しているアドレスはたぶん普通にデータをストアできる場所かもしれません。 しかし文字列としてみた場合、このポインタがさしている先の文字列の長さはゼロですので、strlen(pointer)==0が成り立ちます。 ただし、pointerのさしている先が本当にデータセグメントであるという保証はないので、ゼロ番地以外であってもおかしな場所をさしていれば、代入式は失敗し、セグメンテーションフォルトなどをやはり引き起こします。
あとはC言語での評価順序の問題がありますね。
f(a(x), b(y), c(z)); という関数呼び出しがあったとき、a(x), b(y), c(z)の各関数はどの順で呼ばれるのかCの仕様ではきまっていないのです。 つまりb(y)が呼ばれたあとにc(z)がよばれ、最後にa(x)がよばれ、引数が揃ったところでf()が呼ばれるかもしれません。もしかしたら自動並列コンパイラがa(), b(),c()が互いに素で並列に実行しても問題ないと判断したら並列に処理してしまうかもしれないのです。
ところが、 (a || b)と(a && b)と(a ,b))(カンマ演算子)と(a ? b : c)(三項演算子)では必ずaが先に評価され、その結果次第によってb, cが呼ばれるときまっています。
# ただし、ビット演算子である(a|b)や(a&b)の順序は不定。
このへんを理解していないと、
が何を意味しているのか理解できないわけですね。 この例だと、||では左側が先に評価されると仕様上きまっているので、左項が真(pointer==NULL)であれば右項は評価されず(ORは一つでも真があれば式全体が真になるため)、*pointerに'\0'が代入されることもないのです。Re: (スコア:0)
(必ずしも)ゼロ番地じゃないって。
Re: (スコア:0)
>(必ずしも)ゼロ番地じゃないって。
そうです。「番外地」です。
Re: (スコア:0)
こちら宇宙0番地とか、落ちてもなんとかなるって。
Re: (スコア:0)
NULLポインタはCのソースコード上では定数0で表わしますが、その内部表現(NULLポインタの実際の値)は必ずしも0番地ではないです。x86 CPU など、大抵のマシンでは0番地であることが多いですけど。
Re: (スコア:0)
/* pointerの指し示す先が空文字列の場合 */
...
}
の間違いじゃないのかな?
仮想記憶があるOSで、仮想アドレス空間の0番地の参照はフツーできないようにしてあると思う。「pointer==NULL」の場合、「*pointer」で参照するだけでハードウェア的な例外が発生しますから(NULLセグメントにはそもそもデータを置けないようにする)。NULLセグメントを参照しているプログラムはそもそもバグだし、例外で叩き落すのが吉。