掲示板

掲示板を置いてみました。ご自由に書き込んで下さい。
ただし、私は根性なしなので、閑古鳥が鳴いたり、荒れてきたと
思ったらとっとと閉鎖する可能性があります。


より新しい記事へ ← 500 件の投稿中 400件目〜351件目を表示 → より前の記事へ
表示件数: 件/頁 


400 Re^6: ファイル操作 コメント数:  0件
  レプラコーン 2002/06/04 (火) 19:50
>  tempnam(dir,pfx)のdirにコピー先のディレクトリを指定すれば?
それならば多分、大丈夫だと思われます。

>  uniqueじゃなくなるとかいう。mkstemp()を使うべきだとかって。
_mktemp()ははじめて聞いたのでちょっと調べてみましたが、
_mktemp("/a/tmpXXXXXX")とディレクトリ指定すれば大丈夫そうです。

ただ、どちらもそれぞれに特定条件を持った上限があります。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


399 Re^7: ファイル操作 コメント数:  11件
  本多   | manybook@msc.biglobe.ne.jp 2002/06/04 (火) 16:21
> 必要な場面が少ないんですか。
> バックアップファイルって 元のを消しちゃうのかな?
 これを書いたときは、一般的なアプリケーションがデータファイルを
 上書き保存する際に、元のファイルをback upファイルとする場合の
 ことを考えておりました。
 この場合、バックアップファイルを作成するのに
 move機能があれば、copy機能は使うことはありえないと思ったわけです。

 が、純粋にHDDのバックアップを行うようなユーティリティを
 作ろうと考えた場合、copy機能は必要になりますね。
 失礼しました。

> ほんとは、WindowsでもUNIXでもコンパイルするだけで
> 共通してできるようなものが作りたかったのですが、難しいようですね。
 tempnam()+fopen()+fwrite()+rename()という、私の案は却下されましたか?
 一般的な使用条件下において、問題なく動作しそうに思えますが?

 あれ、tempnam()ってANSIじゃない関数だったのか。
 じゃあ、Windowsにはtempnam()って、ないんですね。
 失礼しました。

 open()関数をO_EXCL付きで呼び出すって言うのも...
 Windowsにはできない技...なんでしょうね。
 そもそもopen()がないか。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


398 Re^6: ファイル操作 コメント数:  14件
  たけちゃん 2002/06/04 (火) 13:58
> > xiuさんの言うように、ファイルのコピー関数が標準関数にないのは
> > 謎ですね。
>  必要な場面が少ないせいだと思いますけど。
>  バックアップファイルならcopyじゃなくて、moveでしょうし。

必要な場面が少ないんですか。
バックアップファイルって 元のを消しちゃうのかな?

ほんとは、WindowsでもUNIXでもコンパイルするだけで
共通してできるようなものが作りたかったのですが、難しいようですね。
MS−DOSのファンクションコールを駆使して作るほうがよさそうなのかなぁ。
>これは、ファイル操作じゃなくて ディスク操作ですが・・・。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


397 Re: 可変長引数をとる関数のラッパー関数を作りたい コメント数:  6件
  本多   | manybook@msc.biglobe.ne.jp 2002/06/04 (火) 13:21
va_listを引数に取るprintf系の関数はvから始まります。
vprintf(), vfprintf(), vsprintf(), vsnprintf(),...
ですから、以下の様に書き直せばやりたいことはうまく行くでしょう。
> n = sprintf( buffer, format, va );
n = vsprintf( buffer, format, va );

ちなみに、snprintf()がある処理系を使っているんでしたら、
sprintf()やvsprintf()ではなく、snprintf(),vsnprintf()を
使うことをお勧めします。

sprintf()は文字列変換後にバッファを溢れさせてしまっても
気にせず文字列を格納し続けてしまうので、
思わぬケガをする危険性があります。

snprintf( buf, size, format,...)は文字列変換後にsizeを
超えるような文字列を格納しません。

文字列変換後の文字列に適切な大きさの領域を確保して
返却値としてポインタを返してくれる関数でもあればいいのにとは
思うのですが、そういう関数ってありましたっけ?>事情に詳しい人

buf = sprintf_with_malloc(format,...);
みたいなの。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


396 Re^5: ファイル操作 コメント数:  16件
  本多   | manybook@msc.biglobe.ne.jp 2002/06/04 (火) 13:01
> > あ〜、rename()は、ファイルシステムが違うとダメだったかな?
> 論理的なディスクを跨る場合の動作も実装依存みたいです。
> そういうわけで、tmpnam()で作成したファイル名でfopen()したものは
> rename()を使用するのは危険だとか。(うーん、ややこしい)
>   →「ANSI C/C++辞典 renameの項」に落とし穴として載っていました。
 この場合、OSのデフォルト ディレクトリのファイルパスを返す
 tmpnam()じゃなくて、ディレクトリ指定ができるtempnam()だったら、
 大丈夫ですかね?
 tempnam(dir,pfx)のdirにコピー先のディレクトリを指定すれば?

 でも、tmpnam()もtempnam()も使わないほうがいいんでしたっけ?
 ファイル名を確定してから、open()までにファイルが
 uniqueじゃなくなるとかいう。mkstemp()を使うべきだとかって。

> xiuさんの言うように、ファイルのコピー関数が標準関数にないのは
> 謎ですね。
 必要な場面が少ないせいだと思いますけど。
 バックアップファイルならcopyじゃなくて、moveでしょうし。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


395 Re: 可変長引数をとる関数のラッパー関数を作りたい コメント数:  0件
  tf 2002/06/04 (火) 12:03

すみません。誤植を見つけましたので訂正させてください

sprintfWrpper -> sprintfWrapper
解説されている籍 -> 解説されている書籍

よろしくお願いいたします
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


394 可変長引数をとる関数のラッパー関数を作りたい コメント数:  8件
  tf 2002/06/04 (火) 11:54

タイトルのままなのですが、どうすればよいのかわかりません。
例えば、sprintfのラッパー関数を次のように書いてみました。

int sprintfWrpper( char *buffer, const char *format, ... )
{
va_list va;
va_start( va, format );
const int n = sprintf( buffer, format, va );
va_end( va );
return n;
}

よくわかっていません(^_^;;
VisualC++で、作成しましたので、各種マクロは以下のようなものです。

#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap) ( ap = (va_list)0 )

最初の引数のアドレスにそれ自身のサイズを加算することによって
次の引数のアドレスを得ているんだろうなあ、というところまでは
わかりました。

動くわけないだろうとお思いのかた、ぜひぜひ、ご教授いただけないでしょうか?
また、この、件に関して、解説されている籍をご存知のかたが
いらっしゃいましたら、お教えいただけないでしょうか。

よろしくお願いいたします



【新規投稿】 【この投稿にリプライ】 【投稿者削除】


393 Re^4: ファイル操作 コメント数:  17件
  レプラコーン 2002/06/04 (火) 11:04
> あ〜、rename()は、ファイルシステムが違うとダメだったかな?
論理的なディスクを跨る場合の動作も実装依存みたいです。
そういうわけで、tmpnam()で作成したファイル名でfopen()したものは
rename()を使用するのは危険だとか。(うーん、ややこしい)
  →「ANSI C/C++辞典 renameの項」に落とし穴として載っていました。

以下の3つの関数はOSに依存度が高く、標準化も難しいと、
「標準Cライブラリ p.320〜p.323」に書いてありました。
  remove()
  rename()
  tmpnam()

最終的にはのぐーさんの教えてくださった
DOSのファンクションコール(でしたっけ?)など
低レベルなルーチンを使ってコピー先、移動先のファイルが
操作元ファイルと同一なのかといいうチェックを
自分で行うしかないみたいですね。
ちょっと面白そうなので、
できるだけ安全なファイルコピー関数でも作ってみようかな。

xiuさんの言うように、ファイルのコピー関数が標準関数にないのは謎ですね。
(それが実装依存になるとしても)
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


392 Re^9: ファイル操作 コメント数:  0件
  xiu 2002/06/04 (火) 08:58
あ、だめなんですか。知りませんでした。

すると、やっぱりCopyFileのようなAPIを使うしかないんですかね。
あらためて指摘されると、ファイルコピーがCの標準関数で与えられない
のはちょっと不思議な感じもします。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


391 Re^8: ファイル操作 コメント数:  1件
  のぐー   | bxm06466@nifty.ne.jp 2002/06/04 (火) 02:30
 http://homepage1.nifty.com/nogue/
> > 当然これはWindowsでも動作します。
>
> Win9x系限定ですよね? 確か。

えっ? NTでも、通常の16ビットアプリは動作するのでは?
intdos()やint86()程度ならエミュレートしてたはず。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


390 Re^7: ファイル操作 コメント数:  2件
  (ぱ)   | PXU00211@nifty.ne.jp 2002/06/04 (火) 02:17
 http://member.nifty.ne.jp/maebashi/
>NTや2000やXPだとCMD.EXEという32ビットアプリを
>起動することになりますが、この時、窓が開くかどうかは知りません。

2000でも、system()でファイルコピーしようとしたらDOS窓が出ました。

> 当然これはWindowsでも動作します。

Win9x系限定ですよね? 確か。

【新規投稿】 【この投稿にリプライ】 【投稿者削除】


389 Re^8: ファイル操作 コメント数:  1件
  のぐー   | BXM06466@nifty.ne.jp 2002/06/04 (火) 01:50
 http://homepage1.nifty.com/nogue/
> ところで、先にfopen(srcfile, "r")しておいてから
> fopen(dstfile,"w")が失敗するかどうかというチェックでは
> 甘いのでしょうか?(特に排他処理を行っていないという前提ですけれど)

やってみるとわかります。
うちでは、fopen(dstfile, "w");は成功し、その瞬間、もののみごとに
ファイルサイズがゼロになりました。

fopen()を使わず、CreateFile()とか_lopen()とかで排他オプションを
指定するという方法もありますが、そもそもこの方法自体、
share.exeが常駐しているか、同等の機能が有効になっている
必要があります。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


388 Re^6: ファイル操作 コメント数:  3件
  のぐー   | bxm06466@nifty.ne.jp 2002/06/04 (火) 01:25
 http://homepage1.nifty.com
>  FUNCTION60Hって、まさか関数名じゃないですよね?
>  一体なんなんですか?Windowsの関数の管理番号?
>  INT21Hって...返却値の型?

INT 21Hというのは、アセンブラでの「割り込み命令」の書き方です。
21Hが割り込み番号になります。(Hがついているので16進数です)
MS-DOSのシステムコールは一部を除きこのINT 21Hで呼び出します。
FUNCTION 60Hというのは、その機能番号が60Hということです。
実際にはAXレジスタの値で指定します。つまりアセンブラだと
MOVE AX 60H
INT 21H
になります。(当然ほかのパラメータも指定しないと駄目)

これをDOS用の16ビットのCコンパイラから呼び出すには、たいていの
DOS用コンパイラにintdos()とかintdosx()とかint86()とかint86x()とかbdos()
とかいうライブラリ関数があるので、これを使います。
例えばVectorからLSI C86試食版というフリーのCコンパイラをダウンロード
してみれば、マニュアルにもこれらライブラリ関数の説明ぐらいは書いてあ
ります。(DOSシステムコールの何番がどういう機能かまでは書いてない)
当然これはWindowsでも動作します。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


387 Re^6: ファイル操作 コメント数:  0件
  のぐー   | bxm06466@nifty.ne.jp 2002/06/04 (火) 01:00
 http://homepage1.nifty.com/nogue/
>  Windowsでは、system()関数を呼び出すと、
>  いちいち、DOS窓が開くんですか?にわかには信じがたいのですが...

開きます。結局のところ、system()というのは、Windows9xや3.xの場合、
command.comという「MS-DOSアプリケーション」を起動するというのが
その動作ですので。(NTや2000やXPだとCMD.EXEという32ビットアプリを
起動することになりますが、この時、窓が開くかどうかは知りません。)

system()ではなくWinExec()等を使い、専用のpifファイル経由で
command.comを起動し、かつSW_HIDEというフラグを指定すれば、
DOS窓を見えなくすることが可能ですが、あまり一般的な手法では
ないようです。(pifファイルを作る必要があるし……)
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


386 Re^7: ファイル操作 コメント数:  2件
  xiu 2002/06/03 (月) 13:59
なるほど。勉強になります。

ところで、先にfopen(srcfile, "r")しておいてから
fopen(dstfile,"w")が失敗するかどうかというチェックでは
甘いのでしょうか?(特に排他処理を行っていないという前提ですけれど)
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


385 Re^5: ファイル操作 コメント数:  5件
  本多   | manybook@msc.biglobe.ne.jp 2002/06/03 (月) 12:41
> むしろGUIプログラムでこれをやると、必ずDOS窓が開くので
> 見栄えが非常によくないというのが最大の問題かも。
 Windowsのプログラムを作成したことがないので、知らないので
 教えていただけると助かります。

 Windowsでは、system()関数を呼び出すと、
 いちいち、DOS窓が開くんですか?にわかには信じがたいのですが...
 system()関数で指定した文字列をDOS窓経由でしか
 コマンドにできないんですか?
 一般に、コマンドの実行とターミナルからのコマンド入力って
 概念が全く異なるものの様に思えるのですが...

> ところでDOSでは、INT21H FUNCTION60Hでファイルの真の名前が確認
> できますが(よってこれで確認すれば、ファイル消失の危険を回避できま
> すが)、同じ機能はWindows APIにはあるのでしょうか?
 FUNCTION60Hって、まさか関数名じゃないですよね?
 一体なんなんですか?Windowsの関数の管理番号?
 INT21Hって...返却値の型?

【新規投稿】 【この投稿にリプライ】 【投稿者削除】


384 Re^6: ファイル操作 コメント数:  3件
  のぐー   | BXM06466@nifty.ne.jp 2002/06/03 (月) 03:29
 http://homepage1.nifty.com/nogue/
> VCのSDKにFindFirstFileという関数がありますが、
> これで取れたと思います。

それはDOSでいうFunction 4Ehです。
Function 60hというのは、SUBSTやJOINやネットワークドライブの割当て
にごまかされない、「真のパス名」を得る機能です。

たとえば、SUBSTコマンドを使って、C:\WINDOWSというパスを
Z:\というパスにわりあてるという機能がDOSにあります。
(Windows95でも使えます。たぶん98やMeでも。)
そうすると、C:\WINDOWS\WIN.COMというパス名と
Z:\WIN.COMというパス名が、全く同じファイルを示すことになります。

元発言を見ていただければわかると思いますが、こういう場合、単に
両方のファイルを、fopen()等で、一方は読込みモードで、もう一方は
書込みモードでオープンしようとすると、書込みモードでオープンし
た瞬間に、ファイルを失います。それを防ぐためには、Z:\WIN.COMが
実はC:\WINDOWS\WIN.COMと同一であることを知る必要があります。
DOSでそれを実現するのが、Function 60hです。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


383 Re^5: ファイル操作 コメント数:  4件
  xiu 2002/06/03 (月) 01:47
> 同じ機能はWindows APIにはあるのでしょうか?

VCのSDKにFindFirstFileという関数がありますが、
これで取れたと思います。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


382 Re^4: ファイル操作 コメント数:  11件
  のぐー   | bxm06466@nifty.ne.jp 2002/06/02 (日) 23:55
 http://homepage1.nifty.com/nogue/
> system()を使う問題点としては GUIプログラムなどで
> 「同一名のファイルがあります。上書きしても良いですかぁ?」
> という、ダイアログウィンドウが作れなくなってしまうかな?

いや、これはできますよ。
単にsystemを呼ぶ前に、書き込みファイルの存在確認をやって
在ったらダイアログを出せば良いだけ。

むしろGUIプログラムでこれをやると、必ずDOS窓が開くので
見栄えが非常によくないというのが最大の問題かも。

ところでDOSでは、INT21H FUNCTION60Hでファイルの真の名前が確認
できますが(よってこれで確認すれば、ファイル消失の危険を回避できま
すが)、同じ機能はWindows APIにはあるのでしょうか?
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


381 Re^3: ファイル操作 コメント数:  30件
  本多   | manybook@msc.biglobe.ne.jp 2002/06/02 (日) 11:06
> よって、dos/Windowsなら
> sprintf(buf, "copy %s %s", src, dst);
> system(buf);
> とかが安全で良いかも。
system()を使う問題点としては GUIプログラムなどで
「同一名のファイルがあります。上書きしても良いですかぁ?」
という、ダイアログウィンドウが作れなくなってしまうかな?

あとは、tempnam()+open()+write()で、仮のファイルにデータを書き込み、
対象ファイル名にrename()すると、
同一ファイルであっても(無駄な操作になりますが)
コピーができるかな?

あ〜、rename()は、ファイルシステムが違うとダメだったかな?
書き込みたいファイルがネットワーク越えてたりすると。
(この場合はmvコマンドも使えないし)
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


380 Re^3: ファイル操作 コメント数:  0件
  レプラコーン 2002/06/02 (日) 00:18
> UNIXならcopyじゃなくてcpだっけ?
UNIXのコマンドはそうですね。

UNIXではstat()でinode番号を調べれば
同一ファイルかどうかって判定できたような気がします。
# UNIXに詳しい方、補足お願いします。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


379 Re^2: ファイル操作 コメント数:  32件
  のぐー   | bxm06466@nifty.ne.jp 2002/06/02 (日) 00:00
 http://homepage1.nifty.com/nogue/
> コピーは自分で作ればいいのかな?

fopen()でコピー元とコピー先をオープンして…というやりかたで、
確かに作れますが、万一、コピー元とコピー先に同じファイルを
指定したりするとファイルを失う危険があります。
ファイル名の文字列を単純に比較するだけでは、この問題を防げません。
(たとえフルパスに直してもダメ。シンボリックリンクとかショートカット
とかシャドウとかjoinとかsubstとか色々とosに依存した機能があるため。)

よって、dos/Windowsなら
sprintf(buf, "copy %s %s", src, dst);
system(buf);
とかが安全で良いかも。
UNIXならcopyじゃなくてcpだっけ?
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


378 Re: ファイル操作 コメント数:  33件
  xiu 2002/05/31 (金) 17:16
stdio.hに
remove // ファイル削除
rename // ファイル移動
があります。コピーは自分で作ればいいのかな?
ただ、ディレクトリ操作などは環境依存のAPIを使う
しかないと思います。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


377 ファイル操作 コメント数:  34件
  たけちゃん 2002/05/31 (金) 10:53
ファイル操作といえば、ファイルの複写、削除、移動かと思うのですが、
そういうのが、あんまりありません。

C言語で上記のことを行うには どうしたらいいでしょうか?
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


376 Re^9: 浮動小数の切り上げ コメント数:  0件
  太田 2002/05/23 (木) 23:02
レプラコーン様、本多様、xiu様

皆様の投稿を拝読させていただき、
納得いたしました。
どうもありがとうございました。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


375 Re^12: 浮動小数の切り上げ コメント数:  0件
  レプラコーン 2002/05/23 (木) 22:08
> このマクロのxの評価回数は私のマクロと同じですね。
はい。書き込んだ後すぐ気が付きました。
最初の私の提示したマクロの問題といい、
こういうポカというか思慮のなさが目立ちますね。
気をつけたいと思います。

また何かあったら、話に参加させてください。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


374 Re^4: ファイルポインタとfclose コメント数:  0件
  喜びの壁   | qf7t-mrt@ashi-net.or.jp 2002/05/23 (木) 19:51
結局のところ、どちらかに書くというよりもその後のデバッグレベルで
わかりやすいようにしておく、という結論でいいのかな.
fcloseとfreeは基本的には似ている関数なんでしょうか、うむ。
> openとcloseの対称性については私も同意します。
遅まきながらご意見ありがとうございました。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


373 Re^11: 浮動小数の切り上げ コメント数:  1件
  xiu 2002/05/23 (木) 10:55
> #define myceil(x) (((x-(long )(x)) == 0.0F) ? (long )(x) : (long )(x+1))
なるほど。確かにこれならうまくいきますね。

> 評価回数が増えてしまっていますが、
?:演算子は第二、第三オペランドのいずれかしか評価されないので、
このマクロのxの評価回数は私のマクロと同じですね。
ですから、レプラコーンさんのマクロのほうが優れていると思います。

どうもありがとうございました。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


372 Re^8: 浮動小数の切り上げ コメント数:  0件
  xiu 2002/05/23 (木) 10:38
> 具体例を教えてくださいますよう願います。

> 関数呼び出しを使いたくない真の理由を
> 教えてくださいますようお願いいたします。

今現在特に必要というわけではないので、具体例というほどのものは
ありません。しかし、本多さんが出して下さった例のように、今後使用する
可能性は否定できなかったので、ceil関数とは別に定数式で解決できる
手段を残しておきたかったのです。
ですから、レプラコーンさんの仰るように、単なるこだわりに過ぎないのかも
しれません。

最初の書き込みの時点では、私がそのときceil関数の存在を忘れてしまって
いたのは事実です。ですが、初期化の問題などがあるために、最初から
関数呼び出しを念頭に置いていなかった(また、その必要性も感じなかった)
ということを付記しておきます。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


371 Re^8: 浮動小数の切り上げ コメント数:  0件
  本多   | manybook@msc.biglobe.ne.jp 2002/05/23 (木) 09:03
> ある整数で初期化しなければならないけれど、、
> 直接、その整数で初期化することは許されず、
> 小数を与えて切り上げなければならない
> 具体例を教えてくださいますよう願います。
具体例はわかりませんが、関連のある2つの数値があったら、
普通は一方から他方を常に自動的に求めるようにしておくでしょう?
#define PI 3.141592653589793
#define CEIL_PI myceil(PI)

と、しておけば、将来PIの値が変更になったときに
CEIL_PIを書き換えずに済むでしょう?
例えば、これじゃ↓2箇所も書き換えるのでめんどくさいでしょう?
#define PI 3.141592653589793
#define CEIL_PI 4
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


370 Re^8: 浮動小数の切り上げ コメント数:  1件
  レプラコーン 2002/05/22 (水) 23:56
こんばんは。はじめまして。
回答側がどういう観点で回答しているかを言うのも何ですが・・・

> ある整数で初期化しなければならないけれど、、
> 直接、その整数で初期化することは許されず、
私はそういう前提条件がある、
もしくは仕事の都合上、そのようにコードを記述したほうが他の作業者に対して値の根源を明示的にできるためそうしたいのでは? と思って回答しています。
設計書に記述、あるいはコメントに記述でもいいでしょうけど。
# 実際問題、初期化時ではなく演算時だけceil()を呼べば
# ほとんどの局面では問題にならないような気はします。


> 実際問題としてはないということであれば、
> 『関数呼び出しを使いたくない理由』を
私は単なる個人的なこだわりと捉えていますが・・・。
このこだわりとマクロの副作用を解決する、ということ=xiuさんの求めるスマートな方法ではないでしょうかね。

ただ、マクロの副作用を気にしているところをみると、
変数使用を前提に考えられているようで、
そうなると静的変数の初期化子に指定できないことを
関数を使用したくない理由にしていることとは矛盾してますけどね。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


369 Re^10: 浮動小数の切り上げ コメント数:  2件
  レプラコーン 2002/05/22 (水) 23:15
> valが1.0e-20のような小さい値に対してもceilが取れるような
評価回数が増えてしまっていますが、一応、以下のもので値「1.0e-20」も平気でした。
マクロに与える値が定数であれば、
定数式になるので静的領域に対する初期化も大丈夫です。(VC++5.0で確認)

#define myceil(x) (((x-(long )(x)) == 0.0F) ? (long )(x) : (long )(x+1))

前回のマクロは丸め誤差を気にしつつも「9」の桁数で精度を調整すればいいか、
なんて考えていたのでちょっと浅はかでしたね。

色々と勉強になりました。ありがとうございます。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


368 Re^7: 浮動小数の切り上げ コメント数:  4件
  太田 2002/05/22 (水) 23:12
はじめまして。

一連の議論を拝読させていただきましたが、
何が問題なのかを全く理解できませんでしたので、
質問させていただきます。

ある整数で初期化しなければならないけれど、、
直接、その整数で初期化することは許されず、
小数を与えて切り上げなければならない
具体例を教えてくださいますよう願います。

> まあ、実際問題として、このように使うことがあるのかどうかは
> わかりませんが、一応これが関数呼び出しを使いたくない理由です。

最初の質問への解答が、
実際問題としてはないということであれば、
『関数呼び出しを使いたくない理由』を
説明したことにはならないと思いますので、
関数呼び出しを使いたくない真の理由を
教えてくださいますようお願いいたします。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


367 Re^9: 浮動小数の切り上げ コメント数:  3件
  xiu 2002/05/22 (水) 16:40
追伸として、
valが1.0e-20のような小さい値に対してもceilが取れるような
演算はあるでしょうか?
私のマクロもこれにはお手上げなんです。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


366 Re^8: 浮動小数の切り上げ コメント数:  4件
  xiu 2002/05/22 (水) 15:40
> 浮動小数→汎整数の型変換は小数切り捨てなので、
> 単純に以下のものでいいのでは?
>
> #define myceil(var) ((long )((var)+0.999999999999999))
>
> 足す値を変えれば四捨五入などにもできますし。

確かに気持ち的にはそのとおりなのですが、
実際にはvarが浮動小数であるため、0.999...との足し算において
演算結果が丸められるかどうかという問題があります。
たとえば、var=1024の場合、足し算の演算結果は
1024.999999999999999ですが、実際には丸められて
1024.999999999999 または 1025.000000000000 になります。
(多分、丸めの方法は処理系依存だと思います。)
そういうわけで、レプラコーンさんの方法は効率はいいのですが、
ちょっと怖いという気もするのです。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


365 Re^7: 浮動小数の切り上げ コメント数:  5件
  レプラコーン 2002/05/22 (水) 15:06
なるほど。やっと何が問題かが判りました。
使用できる局面が絞られるのが嫌なだけですね。
「普通」はと言われたので、切り上げ関数を提示してしまいました。

浮動小数→汎整数の型変換は小数切り捨てなので、
単純に以下のものでいいのでは?

#define myceil(var) ((long )((var)+0.999999999999999))

足す値を変えれば四捨五入などにもできますし。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


364 Re^6: 浮動小数の切り上げ コメント数:  11件
  xiu 2002/05/22 (水) 11:51
> > 関数呼び出しにしたくない理由というのは、初期化式で定数式が
> > 要求される場合にceil関数では初期化できないためです。
> それは以下に示すコードが(外部的な)何らかの理由で使用不可能ってことですか?
> 可能な限り、前提条件などを示して頂けると助かります。
>
"K&R 2Ed. A8.7初期化"に、静的なオブジェクトや配列に対する
初期値式のすべての値は定数式でなければならないとあります。
したがって、次のコードは通りません。

#include<math.h>

double x = ceil(3.1);

int main(void)
{
static double y = ceil(1.2);
return 0;
}

まあ、実際問題として、このように使うことがあるのかどうかは
わかりませんが、一応これが関数呼び出しを使いたくない理由です。

一方で、最初に私が書いたマクロの問題点はというと、xを式中で
3回も評価しているという点だと思います。
何かもっといい方法がありそうなんですが。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


363 Re^6: 浮動小数の切り上げ コメント数:  0件
  レプラコーン 2002/05/22 (水) 03:35
> 変数値を初期化子に指定できないマシンではb[1]の初期化の際にエラーが出ます。
間違えました。
誤)マシン
正)コンパイラ
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


362 Re^5: 浮動小数の切り上げ コメント数:  13件
  レプラコーン 2002/05/22 (水) 03:34
> 関数呼び出しにしたくない理由というのは、初期化式で定数式が
> 要求される場合にceil関数では初期化できないためです。
それは以下に示すコードが(外部的な)何らかの理由で使用不可能ってことですか?
可能な限り、前提条件などを示して頂けると助かります。

-------------------------------
/*
VC++5.0で確認しましたが、b[1], b[2]共に正しく2になりました。
変数値を初期化子に指定できないマシンではb[1]の初期化の際にエラーが出ます。
*/

#include <stdio.h>
#include <math.h>

#define arrayof(var)    (sizeof(var)/sizeof((var)[0]))

int main(void) {
  double a = 0.7;
  double b[] = {
    0.5, ceil(0.4+a), ceil(0.6+0.5)
  };
  int i;

  for(i = 0; i < arrayof(b); i++) {
    printf("%f\n", b[i]);
  }

  getchar();      /* pause */

  return 0;
}
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


361 Re^4: 浮動小数の切り上げ コメント数:  14件
  xiu 2002/05/22 (水) 01:10
> 浮動小数点数から整数への変換も、たいていは関数呼出しに
> なると思いますが。
>
キャストは(少なくとも文法上は)演算子だと思うのですが・・・。
関数呼び出しにしたくない理由というのは、初期化式で定数式が
要求される場合にceil関数では初期化できないためです。

> それに、汎用性を考えるなら、元の値がLONG_MAXより大きい
> ばあいはどうなるのでしょうか?

こっちの事情を言いますと、対数をとった値に対してceilingをとるので
LONG_MAXを超えることはありえません。
そもそも2進の浮動小数を10進数で切り上げるということ自体、
かなりいいかげんな話なのであまり汎用性を追及しても仕方がないと思います。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


360 Re^3: 浮動小数の切り上げ コメント数:  15件
  のぐー   | bxm06466@nifty.ne.jp 2002/05/22 (水) 00:30
 http://homepage1.nifty.com/nogue/
> まあ、あまり関数呼び出しをしたくないという事情はあるんですが、
> 苦しいマクロよりいいかもしれません。

浮動小数点数から整数への変換も、たいていは関数呼出しに
なると思いますが。

それに、汎用性を考えるなら、元の値がLONG_MAXより大きい
ばあいはどうなるのでしょうか?
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


359 Re^2: 浮動小数の切り上げ コメント数:  16件
  xiu 2002/05/21 (火) 00:52
> > 普通、C言語で浮動小数の切り上げを行う場合ってどうするんでしょうか?
> math.hをインクルードしてceil()ではダメですか?

あ。そういえばそんなのもありましたっけ。
まあ、あまり関数呼び出しをしたくないという事情はあるんですが、
苦しいマクロよりいいかもしれません。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


358 Re: 浮動小数の切り上げ コメント数:  17件
  レプラコーン 2002/05/20 (月) 19:55
> 普通、C言語で浮動小数の切り上げを行う場合ってどうするんでしょうか?
math.hをインクルードしてceil()ではダメですか?
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


357 浮動小数の切り上げ コメント数:  18件
  xiu 2002/05/20 (月) 17:57
普通、C言語で浮動小数の切り上げを行う場合ってどうするんでしょうか?

#define ROUNDUP(x) ((long)((long)(x - (long)(x+1))+(long)(x+1)))

私はこんなマクロを作ってみたりするんですが、いまいちダサい感じがします。
他にもっとスマートなやり方があるという方がいらっしゃればご教示ください。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


356 Re^7: ファイルポインタとfclose コメント数:  0件
  てんま 2002/05/13 (月) 15:26
> 0xCCじゃ、味気ないじゃないですか(^^)
x86 系では 0xCC は INT 3 (Debugger Breakpoint) なので
(リアルモードの時代では)意味があったんですよね。
その開放済みメモリを「実行」しようとしたらとまるの。

Visual C++ のデバッグモードなんかは、スタック上の自動変数
領域を 0xCC で初期化します。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


355 Re^6: ファイルポインタとfclose コメント数:  1件
  本多   | manybook@msc.biglobe.ne.jp 2002/05/11 (土) 11:05
> > ただ、間違ってdestroyしたはずのポインタを使ったときに
> > すぐにわかるようにfree()する領域を"0xdeadbeaf"で埋め尽くす
> > というようなことはよくやりますが。
> 私は0xCCですね。WRITING SOLID CODEの流儀です。
0xCCじゃ、味気ないじゃないですか(^^)
0xabadcafeとか0xabadfaceとかでも、いいんですけど。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


354 Re^6: ファイルポインタとfclose コメント数:  0件
  本多   | manybook@msc.biglobe.ne.jp 2002/05/11 (土) 11:03
> > ただ、間違ってdestroyしたはずのポインタを使ったときに
> > すぐにわかるようにfree()する領域を"0xdeadbeaf"で埋め尽くす
> > というようなことはよくやりますが。
>
> これは、ポインタの指す領域を0xdeadbeafで埋め尽くしてfreeする、という
> ことですか?それとも、freeしたポインタに0xdeadbeafを代入するというこ
> とですか?
0xdeadbeafで埋め尽くした後にfreeします。
おっしゃるように
> Cでは一度freeされた領域がその後も値を保持するかどうかは保証されていな
> いはずですし、
freeしたあとの領域は値の保持の保証はありません。
...が、多くの場合、そのポインタを参照すると
中身0xdeadbeafが残っています。
で、freeしたあとのポインタを参照するようなバグが残っていた場合、
このいい加減な値によって、わかりやすい誤動作、運がよければ
Segmentation Faultか、Bus Errorが発生して、freeしたあとの
ポインタを参照しているというバグに気がつきます。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


353 Re^6: ファイルポインタとfclose コメント数:  0件
  のぐー   | bxm06466@nifty.ne.jp 2002/05/11 (土) 04:45
 http://homepage1.nifty.com/nogue/
> そう思って、my_free(void **p) みたいなのを考えたことがありますが、
> 普通にmy_free(p) と書いてもコンパイラが怒らないから使えないなあ、と。
> もちろんHoge_t **ならいいんですが。

#define FREE(p) (free(p),(p)=NULL)
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


352 Re^6: ファイルポインタとfclose コメント数:  0件
  xiu 2002/05/11 (土) 01:36
> > > hoge = HOGE_destroy(hoge); // (こういう使い方を想定されていると信じます)
> ...
> > 私は設計するときはこういう関数にはしませんね。
>
> 同じくです。
>
やっぱりしませんか。いまさら言うのもなんですが、実は私もしません。
ただ、特にダメな理由も思いつかないので書いてみました。
別レスのマクロを使った場合もだめでしょうか?
まあ、マクロですから、
HOGE_DESTROY(fp+0);
が通らなかったりはしますけど...

> > ただ、間違ってdestroyしたはずのポインタを使ったときに
> > すぐにわかるようにfree()する領域を"0xdeadbeaf"で埋め尽くす
> > というようなことはよくやりますが。
>
> 私は0xCCですね。WRITING SOLID CODEの流儀です。

もしかして、「すぐわかるように」っていうのはデバッグレベルでの話だったのですか?だとすると本多さんにはちょっと勘違いしてレスしてしまったようです。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】


351 Re^3: ファイルポインタとfclose コメント数:  0件
  (ぱ)   | PXU00211@nifty.ne.jp 2002/05/10 (金) 22:10
 http://member.nifty.ne.jp/maebashi
> ...ただ、open/close, malloc/free, HOGE_create/HOGE_destroyに
> 常に対象性を持たせて呼び出す階層を一致させるのは大事だとは思いますが。

うーん、揚げ足を取るようですみませんが。

fopen()/fclose()は、たいてい対称性を持たせて書けるでしょうが、
malloc()/free()は難しいですよね。ツリーやグラフを構築するときなんか、
あとでまとめて開放するんでしょうし。
【新規投稿】 【この投稿にリプライ】 【投稿者削除】

Copyright(C) 1999 NIFTY Corporation
All Rights Reserved.