- PR -

C の localtime() の引数は混乱を招く。

投稿者投稿内容
okutin
ベテラン
会議室デビュー日: 2003/12/11
投稿数: 98
お住まい・勤務地: 広島
投稿日時: 2004-09-09 12:54
こんにちは。

Cは元々、構造体そのものを関数の引数として扱うことはできなかったので、構造体を渡す場合はポインタ変数で、構造体を返してもらいたい場合はポインタ変数へのポインタ変数で、というのが普通なのです。

大体、関数内では値の変更はできないし、その値も不定である初期化されていないポインタ変数を関数に渡すことにどんな意味があるのでしょうか?
ぽんす
ぬし
会議室デビュー日: 2003/05/21
投稿数: 1023
投稿日時: 2004-09-09 13:05
引用:

Gioさんの書き込み (2004-09-09 12:26) より:
SYNOPSIS と DESCRIPTION を読むのは当然のことですが、そこを読んでもなぜ time_t ではなく const time_t * を渡すのか、少なくとも RedHat 7.3 のオンラインマニュアルには説明がありません。


いえ、そんな高級な話じゃなくて
カレンダー時刻を引数として、tm構造体に格納されたローカル時刻を
得るための関数なのだから、実体を指さないポインタを引数にしても
意味が無いですよね。SIGSEGV が発生するうんぬん以前の問題として。
コブラ
ぬし
会議室デビュー日: 2003/07/18
投稿数: 1038
お住まい・勤務地: 神奈川
投稿日時: 2004-09-09 15:53
>ポインタ型の仮引数に対しては、実引数の値は必ず確保済みの領域を指すアドレスが、
>直接的ないし間接的(そのアドレスを値として持つポインタ変数)に渡されるものと

せめて、宣言したきりで実体のアドレス代入が無いポインタを不用意に指定した場合コン
パイルエラーでも出してくれりゃエエんですがね。。。なまじ動いてるフリをするから
始末が悪い。

man とかヘッダのプロトタイプだけ見て、そのまんま素直に実体の無いポインタ変数放り
込む人は滅多におらんもんなんでしょうか。引数には実体のアドレスを指定すると一言
でも man で断ってくれりゃエエんですが。。。

わざわざスレッドまで立てた、その趣旨がいまだにわかっとらん「素直な」天然の指摘は
さておき、ある環境、ある状態に遷移して初めて潜在的なミスが顕在化する、そこまで
に至る時間が長過ぎると思う訳ですわ。間違いとはわからず、結果も出てしまう、
これが逆に問題を見えなくしてコストが余計に掛かる。Usage も含めた標準関数の提供の
仕方としてどうなんすかね。 localtime() に限らず。
takubon
常連さん
会議室デビュー日: 2001/11/05
投稿数: 38
投稿日時: 2004-09-09 17:05
 ちょっとコブラ君に質問だけど、コブラ君はlocaltime()を使う時に、引数に何の疑問もなく実体の無いポインタ変数放り込んで、その間違いになかなか気付かなかったの?引数がアドレスかポインタ変数かどっちか迷う事も無く?もしそうだとすると、結構イタイと思うよ。

 少なくともどっちか迷ったんなら、短いコード書いて動かしてみれば、引数がどっちが正しいかわかるよね?今後はちゃんと確認してからコーディングしようね。

 
コブラ
ぬし
会議室デビュー日: 2003/07/18
投稿数: 1038
お住まい・勤務地: 神奈川
投稿日時: 2004-09-09 17:23
実際に動かしても無い人間がノコノコと (プ

大学生ってまだ夏休み中やったっけ?

お前にこそ小一時間問いたいが、もしお前がヘマをやらかすとしたらコンパイル前にソースを
見てる段階でヘマを自分で発見するのか? それともコンパイルしてからヘマを発見する方か?
がるがる
ぬし
会議室デビュー日: 2002/04/12
投稿数: 873
投稿日時: 2004-09-09 17:38
ちっす。がるです。
引用:

struct tm *localtime( const time_t *timer );
こんな風にプロトタイプ宣言されていたら、間違いなくポインタ変数渡してしまう。


そ、そうなんでふか?
単純に「自分がCから入ってるからC言語の特異性に慣れてしまって
おかしさに気づいていない」だけなのかもしれないのですが。
復帰値のポインタは「APIが用意する」ものとして、引数のポインタの
実態は「自分で用意する」ことをごく当然だと思っていたもので。

localtimeの引数にしても(いやまぁなんで値の変更とかないのにポインタ
なんじゃい、ってのはおいておくとして)、実態を用意するのを、
ごく自然にやってました。
const修飾子が付いてるってのもまぁあるので。
# いつか、time_tが構造体とかになる可能性とか見越してたのかなぁ?
# とか好意的に解釈もできます。一応。

引用:

せめて、宣言したきりで実体のアドレス代入が無いポインタを不用意に指定した場合コン
パイルエラーでも出してくれりゃエエんですがね。。。なまじ動いてるフリをするから
始末が悪い。


確かに「偶然」動くこともままありますよね(苦笑
んで、この手のバグって「でっかくなってから」初めて気づくので、
結構デバッグは大変かも、です。
過去に、この手のバグ(他人の関数)で領域破壊されて、print文で
SIGSEGVで落ちて、デバッグにえらい手間取ったことがあります(苦笑
lintとかって最近は見なくなりましたしねぇ。

引用:

man とかヘッダのプロトタイプだけ見て、そのまんま素直に実体の無いポインタ変数放り
込む人は滅多におらんもんなんでしょうか。引数には実体のアドレスを指定すると一言
でも man で断ってくれりゃエエんですが。。。


そういえば。知っている限りでは、実態切らないポインタ変数を
指定する人はそういえばいなかったかも。
でもまぁその辺は「自分の周囲がそもそも特殊」なだけかも
しれないので、なんともいえないのですが。

manに書いてない理由は、多分前提として
・引数にポインタがある場合、実態は自分で用意する
ってのが暗黙の了解なんだと思うですねぇ。

もうちょいシビアに書くと
・そもそも「誰かが実態を用意する」って考えることがおかしい
ってのが多分根底にあって。
だから、引数のポインタってのは、その実態を自分で用意するのが
「当然」なんだろう、と思うです。
# そういう意味で、C言語って低級な言語だと思うのですが :-P

で、APIからの戻り値はさすがに「自分で用意するわけには行かない」
から、やむを得ず「ポインタ変数で受け取っている」だけであって、
ってのが背景にあるように思います。

良くも悪くも「全部自分でやる」文化を背負ってる言語なんだろうと
思うです(少なくともメモリ周りに関しては)。

引用:

Usage も含めた標準関数の提供の仕方としてどうなんすかね。 localtime() に限らず。


背景にある思想の違いのように思うです。
なので「思想が合わなければ違う言語」っていう話になっちゃう
んですかね?
個人的にはむしろ「なんか言語が勝手に領域とか確保してくれちゃう」
ほうが、制御ができなくて怖いのですが :-P
少なくともC言語は、その辺の「メモリへの配慮」ってのは徹底的に
「プログラマがしっかりと考えなければならない」言語だと思う
です。
その辺をよしと見るかあしと見るか、の差のような気も。

でまぁ、その辺のエラーチェックのためにlintとか生まれたんだろう
とは思うのですが。

ただ、メモリ関連を「自分で完全に制御できる」あたりが、ある程度
以上シビアに性能を求められるプログラムで、未だにC言語が使われて
いる理由のようにも思います。

ちっと論点がそれているような気もするのですが。
まぁ、一人の「古いプログラマ」の「カビの生えた感想」ってことで(笑
コブラ
ぬし
会議室デビュー日: 2003/07/18
投稿数: 1038
お住まい・勤務地: 神奈川
投稿日時: 2004-09-09 18:33
流石に、一日の長がある。判り易い。

VC++ みたいにやたらめったら LPCTSTR みたいに、なんでも勘でも参照渡しは止めて
localtime() の戻り値は、tm 構造体へのポインタ、localtime() の引数はいちいち
time_t なんかを typedef せんでも unsigned long の値渡しでエエっ!!

VC++ の LP何とかシリーズにもエラい惑わされましたからな。
Gio
ぬし
会議室デビュー日: 2003/11/28
投稿数: 350
お住まい・勤務地: 都内から横浜の間に少量発生中
投稿日時: 2004-09-09 19:05
コブラさん:
引用:

せめて、宣言したきりで実体のアドレス代入が無いポインタを不用意に指定した場合コン
パイルエラーでも出してくれりゃエエんですがね。。。なまじ動いてるフリをするから
始末が悪い。



C に限って言うと、言語仕様上は宣言だけで初期化されていない変数の値は不定です。
ポインタに限らず、例えば int a; とだけ書いた場合でも a の値は実行するたびに変わる危険性があります。

やはり lint でチェックしておくとか、もしくはすぐ後に代入されることが確定していない変数は初期化しておくとか、そういう習慣がないとトラブルに遭遇しやすいですね。

がるがるさん:
引用:

良くも悪くも「全部自分でやる」文化を背負ってる言語なんだろうと
思うです(少なくともメモリ周りに関しては)。


これに尽きますね。
低レベルコントロールまで許す代わり、リソース管理は全部アプリケーションプログラムの責任というのが C のポリシーなのでしょう。
おかげで正常系でもリソース解放洩れなどのわかりにくいバグが潜んだりしますが、異常系でリソース解放を厳密にやるとやたら面倒になって大変でした(過去形)

スキルアップ/キャリアアップ(JOB@IT)