- PR -

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

投稿者投稿内容
コブラ
ぬし
会議室デビュー日: 2003/07/18
投稿数: 1038
お住まい・勤務地: 神奈川
投稿日時: 2004-09-08 11:16
確かに、大半のバグはコードを書く側に問題があるのでしょう。
しかし、皆さん関数の引数に '*' 付き変数があったとして、果たしてそれが
ある型のポインタ変数を指すものなのか、それともある型の実体の領域のアドレスを指す
のか瞬時に見分けられますか?

まぁ、Cの標準関数に実体の無いポインタ変数だけ渡すなど、殆どあり得ない、と判って
 はいても、私はいまだにできないでいる (プ

 最近では特に、この localtime()。

struct tm *localtime( const time_t *timer );

こんな風にプロトタイプ宣言されていたら、間違いなくポインタ変数渡してしまう。
 実体のアドレスかただのポインタ変数か、明確になっていないところに落とし穴がある
ような気がしますが、戻り値だけはポインタで来るんですな、これが。

 こういうのがバグ発生の確率を上げてしもてるように思いますが、皆さんどうやって
見分けておられるのでしょうか?
ぽんす
ぬし
会議室デビュー日: 2003/05/21
投稿数: 1023
投稿日時: 2004-09-08 12:45
localtime() が何をする関数なのか考えれば、
渡すべきものは明らかでわ?
コブラ
ぬし
会議室デビュー日: 2003/07/18
投稿数: 1038
お住まい・勤務地: 神奈川
投稿日時: 2004-09-08 13:14
それは socket() でも strncpy() でも fputs() でも signal() でも間違いなく何か渡す
でしょう。俯瞰するだけではノウハウは身に付かんけどな (プ
ぽんす
ぬし
会議室デビュー日: 2003/05/21
投稿数: 1023
投稿日時: 2004-09-08 23:12
Cは、マニュアルを読まない人には向きません。
マニュアルを読めばシグナルハンドラをセットして
飛んできたシグナルを捕捉して処理することも難しくない。
マニュアルを読まなければ localtime() だって使えない。
コブラ
ぬし
会議室デビュー日: 2003/07/18
投稿数: 1038
お住まい・勤務地: 神奈川
投稿日時: 2004-09-08 23:59
何? マニュアル通りにさえやればいい恋愛できるって? (プ

一般的に、unix はどんな言語で書かれてると思う?
その unix にはオンライン・マニュアルがあるわな。

逆に言うと、

struct tm *localtime( const time_t *timer );

このプロトタイプの出典は何処からと思てんの?
因みに、俺がソースで使ってるのはこの標準関数だけでは無いけどな (ププ
ぽんす
ぬし
会議室デビュー日: 2003/05/21
投稿数: 1023
投稿日時: 2004-09-09 01:28
引用:

コブラさんの書き込み (2004-09-08 23:59) より:
このプロトタイプの出典は何処からと思てんの?


で、マニュアルは「読んだ」んですか?
DESCRIPTION の項に説明は無かったのですか?
コブラ
ぬし
会議室デビュー日: 2003/07/18
投稿数: 1038
お住まい・勤務地: 神奈川
投稿日時: 2004-09-09 09:32
お前はマニュアル読む前にここ読んだ方がいい。

http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=14550&forum=10&7
Gio
ぬし
会議室デビュー日: 2003/11/28
投稿数: 350
お住まい・勤務地: 都内から横浜の間に少量発生中
投稿日時: 2004-09-09 12:26
SYNOPSIS と DESCRIPTION を読むのは当然のことですが、そこを読んでもなぜ time_t ではなく const time_t * を渡すのか、少なくとも RedHat 7.3 のオンラインマニュアルには説明がありません。
(time_t * であれば引数自体になんらかの補正が施されるとも考えられるのですが、const 付きではそれも違いますし)
この理由が書いてある Unix 系 OS をご存知でしたら、是非ともご教示いただきたく存じます。> ぽんすさん

本題ですが、確かに確かに epoch time からの通算時間を struct tm に変換する関数としては、引数の型が不可解ですね。

ちなみに、宣言だけして初期化されていないポインタ変数を渡し、関数呼び出し後にその変数に適切な値が副作用的に設定されていることを期待する関数もあるにはあります。
もっとも、そういう関数のシグネチャは例えば struct foo *bar(int **baz); とプロトタイピングされており、呼び出す時も
int *p;
struct foo *q;
q = bar(&p);
のようにアドレス渡しになりますが。

ということで、経験上ではありますが、ポインタ型の仮引数に対しては、実引数の値は必ず確保済みの領域を指すアドレスが、直接的ないし間接的(そのアドレスを値として持つポインタ変数)に渡されるものと考えておりますがいかがでしょう。> コブラさん

[ メッセージ編集済み 編集者: Gio 編集日時 2004-09-09 12:34 ]

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