>> int myfunc(void)
>> {
>> conts char funcname[128] = "myfunc" ;
>> printf("%s:%d\t%s" __FILE__,__LINE__,funcname) ;
>> }
>> このBUGの逆版もあり、
>> printf("%s:%d\t%s",__LINE__ , __FILE__,funcname) ;
>> }
>> 解説
>> カンマを忘れたので、__FILE__が書式にくっついたので
>> %sに行番号(__LINE__)がわたって死んだ。
>> 識者の皆様に質問1:
>> このくっ付く文字列を抑止する
>> 良い方法をご存知の方教えてください。
#define MY__FILE__ (__FILE__)
#define MY__LINE__ (__LINE__)
として、必ず MY__FILE__ と MY__LINE__ を使うとか。
printf ("%s:%d\t%s" MY__FILE__, MY__LINE__, funcname);
これならコンパイルできんでしょ、たぶん。
もしくは gcc なら -Wall を付けて、warning は必ずツブすとか。
---
By よこた
私もprintf系でフォーマットに合ってないパラメータを渡してコア
ダンプさせたり、ログファイルに暗号を書き込んでしまったりする
ことはたまにありますが、だからといってそれを防止する方法を考
えようとは思いません。
--
おかはな
tabe wrote:
> このくっ付く文字列を抑止する
> 良い方法をご存知の方教えてください。
カンマを入れる。
> なんで、関数内変数のconstは、
> 省略時staticにならないのでしょうか?
constをつけるかつけないかで、staticだったりautoだったり
ころころ変わるほうがげろげろです。
> const char funcname[128] = "myfunc" ;
> を
> static const char funcname[] = "myfunc"
> と、staticを付けさせて、[]の128を書かせない方法
> 教えてください。
??意味不明です。
--
cog...@sp.hudson.co.jp
株式会社ハドソン
コア・テクノロジー事業本部
システム部 ソフトウェア課
熊岡 忍(Kumaoka Shinobu)
> 識者の皆様に質問1:
> このくっ付く文字列を抑止する
> 良い方法をご存知の方教えてください。
プログラムは書いた通りにしか動きません。当たり前の事なんですけど。
変なつまらないミスを無くすのはプログラマの仕事なんですが、これを
なくしたいというのなら、エディタで変数に色をつけるとか、逆に","
に色をつけるとかすればいいのではないですか?
> 識者の皆様に質問2:
> なんで、関数内変数のconstは、
> 省略時staticにならないのでしょうか?
> スタックに転送する命令が[げろげろ]出て、
> とっても処理速度が遅くなるんですけど、
> const をつけるとなんとなく、dataエリア(UNIXの言葉?)に
> 取られそうなんだけれど、やっぱりスタックにとってる。
const の意味と、static の意味を混同されてるようにお見受け出来るの
ですが、いかがでしょう?
> 識者の皆様に質問3:;
> const char funcname[128] = "myfunc" ;
> を
> static const char funcname[] = "myfunc"
> と、staticを付けさせて、[]の128を書かせない方法
> 教えてください。
C の文法書を良くお読みになった方がいいかと。。。
--
Naohiro Hihara hiha...@post.yamaha.co.jp
http://homepage1.nifty.com/surfweb/
"YOKOTA Yoshinori" <yok...@yynet.tama.tokyo.jp> wrote in message
news:0203200058...@sapphire.yynet.tama.tokyo.jp...
> >> printf("%s:%d\t%s" __FILE__,__LINE__,funcname) ;
> >> カンマを忘れたので、__FILE__が書式にくっついたので
> >> %sに行番号(__LINE__)がわたって死んだ。
> >> 識者の皆様に質問1:
> >> このくっ付く文字列を抑止する
> >> 良い方法をご存知の方教えてください。
>
> #define MY__FILE__ (__FILE__)
> #define MY__LINE__ (__LINE__)
>
> として、必ず MY__FILE__ と MY__LINE__ を使うとか。
> これならコンパイルできんでしょ、たぶん。
意図した通りになりました。
素晴らしい。
#define MY__LINE__ (__LINE__)
で、MY_LINEの展開はこの#defineをした行で、
一律同じになってしまうかと思ったのですが、
大丈夫でした。
よこたさんのアイデアをベースに、
__FILE__と、__LINE__をMIXした、くっ付かないマクロを1時間がかりで作ってみま
した
#define __FILELINE__ (__FILE__ ":" __expand__(__LINE__))
#define __dquote__(X) #X
#define __expand__(X) __dquote__(X)
static void oldmac(void)
{
printf("%s:%d\n",__FILE__,__LINE__) ;
}
static void newmac(void)
{
printf("%s\n", __FILELINE__ ) ;
}
> もしくは gcc なら -Wall を付けて、warning は必ずツブすとか。
これは、私も愛用していますが、
BUGが起きたのは、
my_debug_printf_like()関数でしたので、
gccに、printfの書式と同じチェックをさせる
#pragma printf_like
のような物がれば良いのですが。
ご存知ですか?
> そもそも、
> printf("%s:%d\t%s" __FILE__,__LINE__,funcname) ;
> で、死ぬんだから、死んだ原因を調べれば、すぐわかるんだし、問
> 題ないのでは...?
なんのためのデバッグ文なんだか ;-)
---------------------------------------------------------------------
tesi...@mtf.biglobe.ne.jp
> 私もprintf系でフォーマットに合ってないパラメータを渡してコア
> ダンプさせたり、
>ログファイルに暗号を書き込んでしまったりする
> ことはたまにありますが、
少なくとも2回あったわけですね。
私もあります。
char *str[] ={
"文字列が" //ここでカンマ忘れました
"くっ付いた"
} ;
私の部下もやりました。
そして、今週この問題が又でました。
>だからといってそれを防止する方法を考えようとは思いません。
100人以上の、
複数個所の拠点で、
数千KLINEのプログラムを
合同開発して、
必死に取ったマシンタイムで
このバグが発覚し、
同様問題を、
至急 AM6:00まで調査せよ
って時でも、考えませんか?
簡単なBUGなら、
重要問題にならないとは、
私は考えていません。
以上
-----------------------------------
見て、勝手使って http://rec.ncos.co.jp
この様なアイデアがあれば、
さらに
#define __FILELINE__ (__FILE__ ":" __expand__(__LINE__))
#define __dquote__(X) #X
#define __expand__(X) __dquote__(X)
と、発展させる事ができます。
> > なんで、関数内変数のconstは、
> > 省略時staticにならないのでしょうか?
>
> constをつけるかつけないかで、staticだったりautoだったり
> ころころ変わるほうがげろげろです。
下で解説しますが、
ここで、言いたかった事は、C言語の仕様として
const を付けれ、
関数内でも、
関数外でも、
static を付けようが、付けまいが
静的エリアにデータを割り付ける仕様であれば
良かったのになー。
と言う私の希望です。
>
> > const char funcname[128] = "myfunc" ;
> > を
> > static const char funcname[] = "myfunc"
> > と、staticを付けさせて、[]の128を書かせない方法
> > 教えてください。
>
> ??意味不明です。
ハドソンの熊岡 さんは、恐らく組み込み系だと思いますから、
スタックの貴重さはご存知ですよね。
その1:
関数内で、
char funcname[128] = "myfunc" ;と記述した場合と、
char funcname[] = "myfunc" ;と記述した場合の
どちらがスタックを消費するかも当然ご存知かと思います。
#私はUNIX屋なので、スタック消費は全然気にしませんが、
わざわざ文字列内の文字の数を数える人がいるので。
その2:
関数内で、
static char funcname[] = "myfunc"、と記述した場合と、
auto char funcname[] = "myfunc"、と記述した場合で
実行時どちらが早いか、ご存知ですよね。
#autoのキーワードを使ってる人見た事ないですが、
ここでは強調のため使いました。
その3:
文字列をread only として使用する場合、
static char funcname[] = "myfunc"、と記述した場合と、
static const char funcname[] = "myfunc"、と記述した場合で
どちらが堅牢なプログラムか、
fj.comp.lamg.cの常連の熊岡 さんが知らないわけがない。
で、const を付ければ、書き変えないと宣言したわけだから
コンパイラがわざわざスタックへの転送コードを生成する
理由が私には解らない。と言っているのです。
まとめ:
その1から3までをまとめると、
関数内でread only の文字列は
char funcname[128] = "myfunc" ; と書いてほしくない
static const char funcname[] = "myfunc" と書いて欲しい。
#部下や、発注先の人に。
ここまで書けば、解っていただけますか?
これで駄目なら、
詳細を下に「げっろ」と付けますので、
見て下さい。
--
以上
見て、勝手使って http://rec.ncos.co.jp
―-----------
以下詳細、
趣旨:
/bin/cat vs.c
#define __FILELINE__ (__FILE__ ":" __expand__(__LINE__))
#define __dquote__(X) #X
#define __expand__(X) __dquote__(X)
static void oldmac(void)
{
printf("%s:%d\n",__FILE__,__LINE__) ;
}
static void newmac(void)
{
printf("%s\n", __FILELINE__ ) ;
}
static void Fconst(void)
{
const char funcname[] = __FILELINE__ ;
char buf[1024] ;
printf("%s\n",funcname) ;
}
static void Fstatic(void)
{
static char funcname[] = __FILELINE__ ;
char buf[1024] ;
printf("%s\n",funcname) ;
}
main()
{
int i ;
printf("%s\n",__FILELINE__ ) ;
for(i = 0 ; i < 0x1000 ; i++) {
oldmac() ;
newmac() ;
Fconst() ;
Fstatic() ;
}
}
gcc -O2 `pwd`/vs.c -c
gcc -O2 `pwd`/vs.o -o vs
pixie ./vs -o vs.P
pixie registers: r31, r30, and r21.
old code = 3296 bytes, new code = 12228 bytes (3.7x)
vs.P > /dev/null
----------------------------------------------------------------------------
* -p[rocedures] using basic-block counts; *
* sorted in descending order by the number of cycles executed in each *
* procedure; unexecuted procedures are excluded *
----------------------------------------------------------------------------
442534 cycles
cycles %cycles cum % cycles bytes procedure (file)
/call /line
★212992 48.13 48.13 52 ? Fconst
(/home2/tabe/prof/staticVSconst/vs.c)
65536 14.81 62.94 16 ? oldmac
(/home2/tabe/prof/staticVSconst/vs.c)
☆61440 13.88 76.82 15 ? Fstatic
(/home2/tabe/prof/staticVSconst/vs.c)
61440 13.88 90.71 15 ? newmac
(/home2/tabe/prof/staticVSconst/vs.c)
40980 9.26 99.97 40980 ? main (?)
★staticを付けない場合のサイクル数
☆staticを付けた場合のサイクル数
dis vs.o
**** DISASSEMBLER ****
disassembly for vs.o
section .text
oldmac()
0: 27bdffe8 addiu sp,sp,-0x18
4: 3c050000 lui a1,0x0
8: 24a50004 addiu a1,a1,0x4
c: afbf0010 sw ra,0x10(sp)
10: 27848010 addiu a0,gp,-0x7ff0
14: 0c000000 jal 0x0 <0x0>
18: 24060006 li a2,0x6
1c: 8fbf0010 lw ra,0x10(sp)
20: 00000000 nop
24: 03e00008 jr ra
28: 27bd0018 addiu sp,sp,0x18
newmac()
2c: 27bdffe8 addiu sp,sp,-0x18
30: afbf0010 sw ra,0x10(sp)
34: 3c050000 lui a1,0x0
38: 24a50028 addiu a1,a1,0x28
3c: 0c000000 jal 0x0 <0x0>
40: 27848018 addiu a0,gp,-0x7fe8
44: 8fbf0010 lw ra,0x10(sp)
48: 00000000 nop
4c: 03e00008 jr ra
50: 27bd0018 addiu sp,sp,0x18
Fconst()★staticを付けない場合のコード
54: 3c060000 lui a2,0x0
58: 24c60050 addiu a2,a2,0x50
5c: 27bdfbc0 addiu sp,sp,-0x440
60: afbf0010 sw ra,0x10(sp)
64: 30c20003 andi v0,a2,0x3
68: 10400018 beq v0,zero,0x60 <0xcc>
6c: 27a30018 addiu v1,sp,0x18
70: 24c20020 addiu v0,a2,0x20
74: 27848018 addiu a0,gp,-0x7fe8
78: 88c50000 lwl a1,0x0(a2)
7c: 88c70004 lwl a3,0x4(a2)
80: 88c80008 lwl t0,0x8(a2)
84: 88c9000c lwl t1,0xc(a2)
88: 98c50003 lwr a1,0x3(a2)
8c: 98c70007 lwr a3,0x7(a2)
90: 98c8000b lwr t0,0xb(a2)
94: 98c9000f lwr t1,0xf(a2)
98: a8650000 swl a1,0x0(v1)
9c: a8670004 swl a3,0x4(v1)
a0: a8680008 swl t0,0x8(v1)
a4: a869000c swl t1,0xc(v1)
a8: 24c60010 addiu a2,a2,0x10
ac: b8650003 swr a1,0x3(v1)
b0: b8670007 swr a3,0x7(v1)
b4: b868000b swr t0,0xb(v1)
b8: b869000f swr t1,0xf(v1)
bc: 14c2ffee bne a2,v0,-0x48 <0x78>
c0: 24630010 addiu v1,v1,0x10
c4: 08000040 j 0x100 <0x100>
c8: 00000000 nop
cc: 24c20020 addiu v0,a2,0x20
d0: 27848018 addiu a0,gp,-0x7fe8
d4: 8cc50000 lw a1,0x0(a2)
d8: 8cc70004 lw a3,0x4(a2)
dc: 8cc80008 lw t0,0x8(a2)
e0: 8cc9000c lw t1,0xc(a2)
e4: 24c60010 addiu a2,a2,0x10
e8: ac650000 sw a1,0x0(v1)
ec: ac670004 sw a3,0x4(v1)
f0: ac680008 sw t0,0x8(v1)
f4: ac69000c sw t1,0xc(v1)
f8: 14c2fff6 bne a2,v0,-0x28 <0xd4>
fc: 24630010 addiu v1,v1,0x10
100: 88c20000 lwl v0,0x0(a2)
104: 98c20003 lwr v0,0x3(a2)
108: 80c70004 lb a3,0x4(a2)
10c: 80c80005 lb t0,0x5(a2)
110: 80c90006 lb t1,0x6(a2)
114: a8620000 swl v0,0x0(v1)
118: 27a50018 addiu a1,sp,0x18
11c: b8620003 swr v0,0x3(v1)
120: a0670004 sb a3,0x4(v1)
124: a0680005 sb t0,0x5(v1)
128: 0c000000 jal 0x0 <0x0>
12c: a0690006 sb t1,0x6(v1)
130: 8fbf0010 lw ra,0x10(sp)
134: 00000000 nop
138: 03e00008 jr ra
13c: 27bd0440 addiu sp,sp,0x440
Fstatic()☆staticを付けた場合のコード
140: 27bdfbe8 addiu sp,sp,-0x418
144: afbf0010 sw ra,0x10(sp)
148: 3c050000 lui a1,0x0
14c: 24a50000 addiu a1,a1,0x0
150: 0c000000 jal 0x0 <0x0>
154: 27848018 addiu a0,gp,-0x7fe8
158: 8fbf0010 lw ra,0x10(sp)
15c: 00000000 nop
160: 03e00008 jr ra
164: 27bd0418 addiu sp,sp,0x418
なんか勘違いしてませんか?
# だいたい
# char *strcpy(char *dst, const char *src)
# などのconstが
# > 静的エリアにデータを割り付ける仕様
# だったりしたら困ると思うのだが...。
constは値が変更されないことを保証(プログラマーにも
処理系にも)する宣言なのだから、ある関数内でのみ領
域が確保され、しかもその領域がconstであってほしい
場面だってたくさんあります。
autoかstaticか
constかconstでないか
という2つの選択が直交しているからこそ必要な自由度
が得られるわけで、
> static を付けようが、付けまいが
> 静的エリアにデータを割り付ける仕様であれば
> 良かったのになー。
のように感じるのはconstの主旨を正しく理解していな
いためだと思いますよ。
--
太田純(Junn Ohta) (株)リコー/新横浜事業所
oh...@sdg.mdd.ricoh.co.jp
tabe wrote:
> 質問1:
> このくっ付く文字列を抑止する
> 良い方法をご存知の方教えてください。
共通のヘッダファイルに、
#define __DEBUGPRINT__(a,b,c) printf("%s:%d\t%s",a,b,c)
と置いて、
デバッグ印字させたいところに、
__DEBUGPRINT__(__FILE__,__LINE__,funcname) ;
と入れる。
ヘッダファイルの方は、放っておいても使わなければ、問題なし。
(コンパイラの余計な仕事にはなるかもしれないけど)
あるいは余りお勧めできないけど、
#define __DEBUGPRINT__ printf("%s:%d\t%s",__FILE__,__LINE__,funcname)
として
__DEBUGPRINT__ ;
でも可のはず。
> 質問2:
> なんで、関数内変数のconstは、
> 省略時staticにならないのでしょうか?
> スタックに転送する命令が[げろげろ]出て、
> とっても処理速度が遅くなるんですけど、
それは、automatic変数をconst宣言したから、
無理矢理、スタック上にコピーする必要が発生しているのでは?
> const をつけるとなんとなく、dataエリア(UNIXの言葉?)に
> 取られそうなんだけれど、やっぱりスタックにとってる。
逆アセンブル結果を見ると、dataエリアにもとって、
それをスタック領域にコピーしなおしているように見えますが?
> 74: 27848018 addiu a0,gp,-0x7fe8
この-0x7fe8って、"myfunc"じゃないですか?
(oldmac,newmac,Fconst,Fstaticの全てに共通して存在しています)
> 質問3:
> const char funcname[128] = "myfunc" ;
> を
> static const char funcname[] = "myfunc"
> と、staticを付けさせて、[]の128を書かせない方法
> 教えてください。
staticにする意味がないと思うから、下記の通り。
char *funcname = "myfunc" ;
static宣言しても、問題は全くなし。
static char *funcname = "myfunc" ;
> 追記:
> 自動変数は、スタックにとるとは限らないの
> 突っ込みはここではしないで下さい。
え゛、自動変数はスタックにしか取られないと思いますが?
(このルール勝手に変えられると、リカーシブコールが出来なくなるぅぅぅ(^^;
)
以上、全然ご参考にはならないと思いますが、私なりの回答でした。
> カンマを入れ忘れるから、
> 入れ忘れを防止する方法がありませんか?と
> 聞いているのです。
> ですから、ここで私が期待する答えは、
> よこた氏が書いてくれた、
> #define MY__FILE__ (__FILE__)
> の様なアイデアです。
思うのですが、入れ忘れているかどうかの判定は C 言語の範囲の外ですよね。
入ってないのが意図した動作かもしれませんので。
# 今回は printf の書式と合わないので、間違っているということが分かりま
# すけれど。
自前で check ツールを作るという手段は駄目なのでしょうか? cpp を通した
結果を perl script なり yacc&lex で作成したツールに渡すなりして、です。
追加でツールを作成すると、そのツール自身がバグを持っている可能性を否定
できませんけど…
つなげて使いたい時には __FILE__、つなげて使いたくない時には MY__FILE__
となるのは、それはそれで混乱のもとかと思うのです。
# つなげて使うことはありえない、ならいいのかなぁ。
> static char funcname[] = "myfunc"、と記述した場合と、
> auto char funcname[] = "myfunc"、と記述した場合で
この比較はまずいでしょう…。明らかに想定している使い方が違うかと。
> 文字列をread only として使用する場合、
> static char funcname[] = "myfunc"、と記述した場合と、
> static const char funcname[] = "myfunc"、と記述した場合で
こちらは「read-only として使用したい」という意図が判明しないとできない
操作ですよね。C compiler がどっちが正しいかを判定するのは、困難ではあ
りませんか?
また、
const char funcname[] = "myfunc" ;
static const char funcname[] = "myfunc" ;
同士にしても、"myfunc" が何処に置かれているかが気になります。外してい
るかもしれませんが、ROM/RAM がバンク切り替えで動作するような処理系だと、
"myfunc" が非常に頻繁に参照される場合、"myfunc" を見るためのバンク切り
替えが発生しなくなって前者の方が軽くなるかも…。
いずれにせよ、C の仕様の範囲ではないような気がするのですが。
--
---
Takashi SAKAMOTO (PXG0...@nifty.ne.jp)
> え゛、自動変数はスタックにしか取られないと思いますが?
些細なツッコミですが、register にのる可能性があります。local 変数で
address が必要ない場合などに。
# -O2 付きで作った execute file を gdb で debug していると、register
# にのっていたと覚しき変数の値が参照できなくなっていて、「ま、仕方ない
# か」と思うことが。
gcc 独自拡張のものでも良ければ、
__attribute__ ((format (printf, x, y)))
っていうのはどうでしょうか?。info マニュアルでは
gcc → C Extensions → Function Attributes に解説があります。
---------------------------------
宮坂 賢 (Miyasaka, Masaru)
Asahikawa-City, Hokkaido, Japan
e-mail : alk...@coral.ocn.ne.jp
まったく、そのとおりですね。
でも、デバッグ用のコードをデバッグする羽目になる可能性はデバッ
グ用のコードを入れる限り常にあります。
バグが入りにくいように工夫する努力は必要かと思いますが...
a += 10;
を
a + 10;
と間違えたら、今度は
#define ADD(x,y) x += y
なんてマクロを発明するのでしょうか...?
--
"MIYASAKA Masaru" <alk...@coral.ocn.ne.jp> wrote in message
news:a7bhmv$rka$1...@nn-tk103.ocn.ad.jp...
―――――――――――――――――――
> > 質問2:
> > なんで、関数内変数のconstは、
> > 省略時staticにならないのでしょうか?
> > スタックに転送する命令が[げろげろ]出て、
> > とっても処理速度が遅くなるんですけど、
>
> それは、automatic変数をconst宣言したから、
> 無理矢理、スタック上にコピーする必要が発生しているのでは?
うう、これが皆、解ってくれないんです。
私も解ってないいんですけど、
「書き換えて駄目」のconstを、スタックにコピーする
必然性が私には解らないんです。
>
> > const をつけるとなんとなく、dataエリア(UNIXの言葉?)に
> > 取られそうなんだけれど、やっぱりスタックにとってる。
>
> 逆アセンブル結果を見ると、dataエリアにもとって、
> それをスタック領域にコピーしなおしているように見えますが?
そうです。
constを付けて「書き換えては駄目」とプログラマが
明記しているのに、
なんでわざわざ、
「スタック領域にコピーしなおしている」のか、
私には解らないのです。
> > 74: 27848018 addiu a0,gp,-0x7fe8
>
> この-0x7fe8って、"myfunc"じゃないですか?
> (oldmac,newmac,Fconst,Fstaticの全てに共通して存在しています)
あ、これは
"%s\n"の事です。oldmacには無いです。
>
>
> > 質問3:
> > const char funcname[128] = "myfunc" ;
> > を
> > static const char funcname[] = "myfunc"
> > と、staticを付けさせて、[]の128を書かせない方法
> > 教えてください。
>
> staticにする意味がないと思うから、下記の通り。
>
> char *funcname = "myfunc" ;
>
> static宣言しても、問題は全くなし。
>
> static char *funcname = "myfunc" ;
これで十分なんですが、
C-FAQ 1.32の事を部下に理解して欲しいな、、て事で。
> > 追記:
> > 自動変数は、スタックにとるとは限らないの
> > 突っ込みはここではしないで下さい。
>
> え゛、自動変数はスタックにしか取られないと思いますが?
> (このルール勝手に変えられると、リカーシブコールが出来なくなるぅぅぅ(^^;
> )
えっと、これは、「自動変数がスタックに取られる」って書くと
お約束で、そんな規約は無いって突っ込みがるので、
面倒なので書きました。
正確な説明は、
http://www2s.biglobe.ne.jp/~hig/q_a/Programing_QA03.html#Q3
の、
「3. C では、関数内で宣言した自動変数はスタック上に確保されるのか? 」
を、お読みください。
>
> 以上、全然ご参考にはならないと思いますが、私なりの回答でした。
解ってくれて感謝してます。
> # 今回は printf の書式と合わないので、間違っているということが分かりま
> # すけれど。
> 自前で check ツールを作るという手段は駄目なのでしょうか? cpp を通した
> 結果を perl script なり yacc&lex で作成したツールに渡すなりして、です。
駄目でないです。
ぜひ、作って下さい。
完成したならば、
ぜひ、r...@ncos.cp.jpへご連絡してください。
使用権ならば、ビール券を差し上げます。
ソースコードを頂けるならば、
「ライセンス料金」ご相談に応じます。
> 追加でツールを作成すると、そのツール自身がバグを持っている可能性を否定
> できませんけど…
> つなげて使いたい時には __FILE__、つなげて使いたくない時には MY__FILE__
> となるのは、それはそれで混乱のもとかと思うのです。
> # つなげて使うことはありえない、ならいいのかなぁ。
えーと、だから混乱を最小限に留める、
__FILELINE__の作り方を示したのですが。。。。。
>
> > static char funcname[] = "myfunc"、と記述した場合と、
> > auto char funcname[] = "myfunc"、と記述した場合で
>
> この比較はまずいでしょう…。明らかに想定している使い方が違うかと。
すみません、
なにが、まずいのですか?
constとstaticの使い方と違いが解ってないと、
袋叩きに、あっている私にも解る様に説明願います。
どのへんの、比較がまずいですか?
>
> > 文字列をread only として使用する場合、
> > static char funcname[] = "myfunc"、と記述した場合と、
> > static const char funcname[] = "myfunc"、と記述した場合で
>
> こちらは「read-only として使用したい」という意図が判明しないとできない
> 操作ですよね。C compiler がどっちが正しいかを判定するのは、困難ではあ
> りませんか?
はい。C compiler には解りません。
ですが、
プログラマには、解っているはずです。
だから、
プログラマに、constと書けと言っているつもりなんですが。。。
>
> また、
>
> const char funcname[] = "myfunc" ;
> static const char funcname[] = "myfunc" ;
>
> 同士にしても、"myfunc" が何処に置かれているかが気になります。外してい
> るかもしれませんが、ROM/RAM がバンク切り替えで動作するような処理系だと、
> "myfunc" が非常に頻繁に参照される場合、"myfunc" を見るためのバンク切り
> 替えが発生しなくなって前者の方が軽くなるかも…。
えっと、
私はUNIX屋で、
組込み屋さんでありません。
ですが、推測で大体解ります。
const char funcname[] = "myfunc" ;
と記述すると、RAM
static const char funcname[] = "myfunc" ;
と記述すると、ROM。
「バンク切り」につては、
実測値が欲しいです。
「前者の方が軽くなるかも…。」は書かなくて良いです。
>
> いずれにせよ、C の仕様の範囲ではないような気がするのですが。
えーと、
C言語の仕様(を作成した人の)努力の範囲外と
Cコンパイラ(を作成した人の)努力の範囲外と、
Cプログラム(を作成した人の)努力の範囲外と、
ありますが、
何が、
誰の、
範囲外とお考えですが。
> ---
> Takashi SAKAMOTO (PXG0...@nifty.ne.jp)
――――――――――――――――――
> で、const を付ければ、書き変えないと宣言したわけだから
> コンパイラがわざわざスタックへの転送コードを生成する
> 理由が私には解らない。と言っているのです。
constつけた変数には代入はできませんが初期化はできます。
例えば
int func(int in)
{
const int new_in = in - 1; /* これは初期化 */
/* この関数内では new_in 書き換え不可
inは書き換えOK */
/* 処理 */
if (new_in > 0) /* 終了条件 */
return func(new_in); /* 再帰! */
else
return new_in;
}
この関数 func()は再帰呼出されているため、new_inは自動変数である必要が
あります。そうでないと func()が再入可能にならず意図した動作をしません。
以上、constつきの自動変数の必然性の一例でした。
でかいの企画 佐々木茂彦
ssa...@dekaino.net
なんか、全然話しが噛み合わないので、
歴史的(私の解釈の)順をおって説明します。
(1) K&Rの時代ではできなかった、
autoの集成体型の初期化が、ANSI-Cで出来る様になった。
※これは便利だ。
http://www.catnet.ne.jp/kouno/c_faq/c1.html
(2) だからといって、
autoの集成体型の初期化を多用するな、
処理速度の劣化とスタックの浪費を招く事になる。
http://www.catnet.ne.jp/kouno/c_faq/c1.html
(3) constで関数内の自動変数を修飾したならば、
staticを付けた方が良い場合が多い。
http://www.st.rim.or.jp/~phinloda/cqa/cqa14.html
(4) 初期値を持つ(初期化をする)自動変数に、
constを付けても、
処理速度の劣化とスタックの浪費の解決には、
なんの役にも立たない。
特に集成体型に対して、
constだけ付けてstaticを付けないと、
処理速度の劣化とスタックの浪費は顕著である。
(5)ここですね、
(a) static × const 私でも解る
(b) static × !const 私でも解る
(c) auto × !const 私でも解る
(d) auto × const ★私には、解らない
(d) の、「ある関数内でのみ領域が確保され、しかもその領域がconstで
あってほしい」
書き換えては駄目のconstオブジェクトを、
わざわざ、書き換え可能なスタック領域にコピーしなければならない
必然性が私には解らない。
※スタック消費と、転送処理実行時間を犠牲にしてまで、
「書き換えては駄目」~=「read only]
の、constオブジェクトをなんで、
スタック領域にコピーするのだろう
と言うのが、私の疑問です。
太田さん、
関数の引数定義の所で、データ領域の記述が出来るのは
registerだけのはず。
>ある関数内でのみ領域が確保され、
スタックの表現をしていいですね。
駄目であれば、
「自動変数あ格納される領域」でもいいですけど、
>しかもその領域がconstであってほしい
その領域を書き換えては駄目って事ですよね。。
> 場面だってたくさんあります。
無いです。
すくなくても、
たくさんは無いです。
「関数突入時に、スタックにわざわざ書き換えては駄目のデータ転送」
しなければ
ならない場面の、たくさんの内の一つを
私に教えてください。
これは私の表現だから
大田さんの表現の、
「 ある関数内でのみ領
域が確保され、しかもその領域がconstであってほしい
場面だってたくさんあります。
」
ってどんな場面????
私には、思いつかない。
> --
> 太田純(Junn Ohta) (株)リコー/新横浜事業所
> oh...@sdg.mdd.ricoh.co.jp
――――――――――――――――――
tabe wrote:
> 感謝してます。
> 私の疑問を一番正確に理解してくれたのは、
> 田村さんです。
きっと、そんなことは無いんじゃないかな?(^^;
> > #define __DEBUGPRINT__ printf(以下略)
> > として
> > __DEBUGPRINT__ ;
> > でも可のはず。
> これを、関数っぽくして、機械的に、
> 関数の頭にポッポッポと入れるのには一番楽ですね。
> 可変引数のダンプをしたい時は、ちょと難点ですが。
それは、デバッグ時に掛ける工数とのわりきりだと思う。
デバッグ時にデバッグルーチンのデバッグに追われるよりはマシかと?
もし、可変引数のダンプをしたいなら、__DEBUGPRINT__の後に
printf("line:%d 書式",__LINE__,~);
と、書式の直後を数値にさせれば、コンパイラが教えてくれるんじゃ
ないかな?<単純なコーディングミス。
その例がif(定数 == 変数)だと思う。<作法
(私は守らないけど(笑))
> > > 質問2:
> > > なんで、関数内変数のconstは、
> > > 省略時staticにならないのでしょうか?
> > それは、automatic変数をconst宣言したから、
> > 無理矢理、スタック上にコピーする必要が発生しているのでは?
> うう、これが皆、解ってくれないんです。
> 私も解ってないいんですけど、
> 「書き換えて駄目」のconstを、スタックにコピーする
> 必然性が私には解らないんです。
これは単にautomaticが優先しているからでは?
(スタック上別アドレスでも)再度呼び出された場合に、
内容の保証を行う必要があるからこそ、
コピー作業が必要になるのではないでしょうか?
(最近流行のスタックオーバーフロー攻撃にも対応できるとか?((((^^;)
私に示した
> http://www2s.biglobe.ne.jp/~hig/q_a/Programing_QA03.html#Q3
> の、
> 「3. C では、関数内で宣言した自動変数はスタック上に確保されるのか? 」
の説明にあった
「それが宣言されているブロックへ正常に入るごとに、(中略)
記憶域を確保することを保証する。」
がそのまま答えなのでは?
(このため、constであっても領域の共有ができないだけかと)
> > > 74: 27848018 addiu a0,gp,-0x7fe8
> >
> > この-0x7fe8って、"myfunc"じゃないですか?
> > (oldmac,newmac,Fconst,Fstaticの全てに共通して存在しています)
> あ、これは
> "%s\n"の事です。oldmacには無いです。
でしたね(^^ゞ
きっと、こっちですね
> 34: 3c050000 lui a1,0x0
ところで、これってSPARCっすか?<CPU
> > > 質問3:
> > > const char funcname[128] = "myfunc" ; を
> > > static const char funcname[] = "myfunc"
> > > と、staticを付けさせて、[]の128を書かせない方法
> > > 教えてください。
> > staticにする意味がないと思うから、下記の通り。
> > char *funcname = "myfunc" ;
> > static宣言しても、問題は全くなし。
> > static char *funcname = "myfunc" ;
> これで十分なんですが、
> C-FAQ 1.32の事を部下に理解して欲しいな、、て事で。
一瞬ドコ?って聞こうと思ったけど、
太田さん宛てのResにあったので、とりあえず解決。
ただ、それを理解してない人にプログラミングさせる時点で
無茶だと思う(^^;
1からちゃんと教えないと、後々苦労しますよ?
(って、今でもしてるんでしたっけ)
記憶域の管理って、ある意味一番重要だと思うんですが。
C言語って、そのへんの自由度が高いからこそ、それに見合う技量を
要求される言語だと私は思っています。
> > > 追記:
> > > 自動変数は、スタックにとるとは限らないの
> > > 突っ込みはここではしないで下さい。
> > え゛、自動変数はスタックにしか取られないと思いますが?
> > (このルール勝手に変えられると、リカーシブコールが出来なくなるぅぅぅ(^^;
> > )
> えっと、これは、「自動変数がスタックに取られる」って書くと
> お約束で、そんな規約は無いって突っ込みがるので、
> 面倒なので書きました。
> 正確な説明は、
> http://www2s.biglobe.ne.jp/~hig/q_a/Programing_QA03.html#Q3 の、
> 「3. C では、関数内で宣言した自動変数はスタック上に確保されるのか? 」
> を、お読みください。
とりあえず読ませていただきましたm(__)m
私的には、リカーシブコールがちゃんと出来れば、どこでも可(笑)
Takashi SAKAMOTO wrote:
> > え゛、自動変数はスタックにしか取られないと思いますが?
> 些細なツッコミですが、register にのる可能性があります。local 変数で
> address が必要ない場合などに。
そういえば、そんなのもありましたね~<register属性
x86ベースでやってると、register宣言自体が勿体なくて、
すっかり忘れてました(笑)
> # -O2 付きで作った execute file を gdb で debug していると、register
> # にのっていたと覚しき変数の値が参照できなくなっていて、「ま、仕方ない
> # か」と思うことが。
一昔以上前にMS-C 3.0にやられました(^^;
クロスリファレンステーブルから、ローカル変数のアドレス見つけて、
デバッガで見てたら、実はregister上で操作されてたって事が。
ただ、どちらにせよ、リカーシブコールする際に記憶域保持がちゃんと
行われるのであれば、私的にはおっけ~です。
本来の答えは、tabeさんの私宛てのresにあります。
tabe wrote:> カンマを入れる。
> カンマを入れ忘れるから、
> 入れ忘れを防止する方法がありませんか?と
> 聞いているのです。
結局、文字列リテラルの連結を抑制したいのか、
カンマの入れ忘れを防止したいのか、どちらなんでしょう?
> と言う私の希望です。
私の希望とは違います。
> ハドソンの熊岡 さんは、恐らく組み込み系だと思いますから、
> スタックの貴重さはご存知ですよね。
組み込み系ではありませんが、スタックの貴重さは知っているつもりです。
> 関数内でread only の文字列は
> char funcname[128] = "myfunc" ; と書いてほしくない
> static const char funcname[] = "myfunc" と書いて欲しい。
気持ちはわからんでもありませんが、コンパイラの仕様の所為にしても
しかたがないでしょう。
char funcname[128] = "myfunc";
という書き方が、Cの仕様として正当である以上、禁止することは無理だと思うのですが。
(1)~(4)については異義ありません。というか、そのあ
たりに異義のある人はここにはいないでしょう。
> 「関数突入時に、スタックにわざわざ書き換えては駄目のデータ転送」
> しなければ
> ならない場面の、たくさんの内の一つを
> 私に教えてください。
(a) その関数の複数のインスタンスが同時に存在する
(b) (a)のそれぞれの関数インスタンスで固有のデータ
を生成して利用したい
(c) (b)のデータがconstであってほしい
という条件が成立するときですね。
(a)については、直接あるいは間接に再帰呼び出しを行
う関数か、あるいはstaticな領域を共有するようなマル
チスレッドで呼び出される関数で成立するでしょう。
(b)については、たとえばその関数の内部で定数となる
値を利用したいが、その定数が関数引数に演算あるいは
キャストを施して得られるようなものであった場合など
ですね。もちろんそれらの「定数」を利用するすべての
場面にもとの関数引数を用いた式を書いてもいいわけで
すが、その式が複雑ならわざわざ(一度だけ)計算結果を
スタックに転送する価値もある、と。
(c)についてはとくに説明の必要はないでしょう。変更
されない値には無条件にconstを付けたい。
> 関数の引数定義の所で、データ領域の記述が出来るのは
> registerだけのはず。
え? constも使えますが...???
お使いの処理系のインクルードファイルを見ると関数プ
ロトタイプにconstの記述がわんさかありませんか?
> >ある関数内でのみ領域が確保され、
> >しかもその領域がconstであってほしい
> > 場面だってたくさんあります。
> 無いです。
> すくなくても、
> たくさんは無いです。
「たくさん」かどうかは評価の分かれるところかもしれ
ませんが、少なくとも、上に私が示した例は「constな
ら自動的にstaticになる仕様のほうがよい」を否定する
にじゅうぶんなサンプルであると思うのですけどね。
fj.comp.lang.cの記事<a7cmba$aht$1...@bgsv5906.tk.mesh.ad.jp>で
ta...@mug.biglobe.ne.jpさんは書きました。
> 「書き換えて駄目」のconstを、スタックにコピーする
> 必然性が私には解らないんです。
「constをスタックにコピーする」のではなくて、「何
がしかの値をスタックにコピーして、その結果がconst
になる」です。
その「何がしかの値」を求めるためにコストがかかるよ
うな場合、あるいはその「何がしかの値」を何度も求め
なければならない場合には、「スタックにコピーする」
コストをかけても引き合うことがあるわけです。
これでもまだ「必然性」が見えませんか?
> # -O2 付きで作った execute file を gdb で debug していると、register
> # にのっていたと覚しき変数の値が参照できなくなっていて、「ま、仕方ない
> # か」と思うことが。
ちゃんと相当する情報は出力されているはずなんですけどねえ.
gcc-2.8.0 + gdb-4.13 (x86 a.out format) でさっき試してみましたが,
print 変数名
で %eax にしか存在しない値がちゃんと確認出来ました.
# 古いバージョンを手放せない理由の一つ :-)
gdb のマニュアルにも「レジスタ変数は読めないことがある」とかあって, 実
際初期の gdb は読めなくて, いつ頃からか「おお, 読めるやん」とかで感動
してたのにこれまたいつ頃からか読めなくなってるという….
--
Kazuo Fox Dohzono / doh...@hf.rim.or.jp
マニュアルが、ですか?。gcc マニュアルの日本語訳って、
私はまだ一度も見たこと無いんですけど(^^;。
http://www.sra.co.jp/wingnut/gcc/index.html
にありますよ。あとは
ftp://ftp.ascii.co.jp/pub/GNU/
に各種GNUツールの日本語訳されたTeXinfoもあります。
--
/*-------------------------
alf...@sainet.or.jp
岡崎 次朗
-------------------------+/
MIYASAKA Masaru wrote:
> tabe <ta...@mug.biglobe.ne.jp> wrote in message
> news:a7ckqt$94g$1...@bgsv5906.tk.mesh.ad.jp...
> > さすが、gccなんでも有るんですね。
> > ところで、日本語ですか?
> マニュアルが、ですか?。gcc マニュアルの日本語訳って、
> 私はまだ一度も見たこと無いんですけど(^^;。
infoの日本語訳は私も見たこと無いけど、
man の日本語訳なら、FreeBSDのページにあります。
http://www.jp.freebsd.org/man-jp/search.html
そしたら、こんなの見つけました。
-Wformat
printf, scanf などへの呼び出しに対して、与えられた
引数が、フォーマット文字列の指定を満足する型を持っ
ているかを検査します。
と、裏で検索していたら、こんなところにあった。
さすが、SRAさん。
http://www.sra.co.jp/wingnut/gcc/
ちなみに、お探しのものは、gcc-j.info-10 の中にあるようです。
具体的な例として、以下のxなんていかがでしょう?
typedef int keytype;
void quicksort(keytype a[], int first, int last)
{
int i, j;
keytype t;
const keytype x = a[(first + last) / 2];
i = first; j = last;
for (;;) {
while (a[i] < x) i++;
while (x < a[j]) j--;
if (i >= j) break;
t = a[i]; a[i] = a[j]; a[j] = t;
i++; j--;
}
if (first < i - 1) quicksort(a, first, i - 1);
if (j + 1 < last) quicksort(a, j + 1, last);
私は、C言語の const は、言語仕様上の失敗に近いかなあという
気がします。volatile は、いいけど。
In article <a7e3cb$29r$1...@ns.src.ricoh.co.jp>
oh...@src.ricoh.co.jp (Junn Ohta) writes:
> (b)については、たとえばその関数の内部で定数となる
> 値を利用したいが、その定数が関数引数に演算あるいは
> キャストを施して得られるようなものであった場合など
> ですね。もちろんそれらの「定数」を利用するすべての
> 場面にもとの関数引数を用いた式を書いてもいいわけで
> すが、その式が複雑ならわざわざ(一度だけ)計算結果を
> スタックに転送する価値もある、と。
こんなの、別にコンパイラが解析して、勝手にやればいいのであっ
て、人間にわざわざ const と書いてもらう必要はないでしょ。
つまり、コンパイラの技術が進めば、const は不要になると。
今の技術、特に部分評価系なんか、関数を越えて不変量を見つるこ
とができます。
http://compose.labri.fr/prototypes/tempo/
今のコンパイラで、const と書いた時と書いていない時で実行効率
がどのくらい変るものでしょう?
コンパイラは、const と書いてあっても書いて同じとなると、あと
は、const が、プログラマにとって訳に立つかです。const の意味
は、わかりにくくて、そんなに訳に立てられる人はたてられるでしょ
うが、一般庶民のプログラマには難しいんじゃないかなあ。私も自
分のCのプログラムで「これは const と書きたい」と思ったこと
もないし、書いた記憶はないです。
結局、コンパイラも人間もあんまり役には立てなくて、言語仕様と
しても、今一つだったかなあということです。
ポインタでてると、話がさらに訳がわからなくなります。const の
ポインタの 、ポインタの先が const、ポインタも const で、ポイ
ンタの先も const、、、あんまり考えたくはない話です。
const ではなくて、static を拡張して、static_and_const みたい
なものだったら、ROM化できるとか、意味がつけやすかったかなあ。
fj の議論なので、「言語仕様だから終わり」で終わるんじゃなく
て、その言語仕様は、そもそもよかったのか、と発展させたいです。
> お使いの処理系のインクルードファイルを見ると関数プ
> ロトタイプにconstの記述がわんさかありませんか?
そう。時々、コンパイラできなくて。これで、const が入ったため
に、幸せになった、と言えるんですかね。
In article <a7eh82$64d$1...@ns.src.ricoh.co.jp>
oh...@src.ricoh.co.jp (Junn Ohta) writes:
> 具体的な例として、以下のxなんていかがでしょう?
> typedef int keytype;
> void quicksort(keytype a[], int first, int last)
> {
> int i, j;
> keytype t;
> const keytype x = a[(first + last) / 2];
quick sort は、もともと関数的なアルゴリズムだから、単一代入
の変数が出てくるんですよね。このくらいは、コンパイラが解析で
きるでしょう。あと、単一代入という考え方はよいとしても、
「auto 変数がスタックにある」というようなメモリの考え方と単
一代入の考え方は馴染みません。そういう意味でも const がイマ
イチなんだと思います。
\\ 新城 靖 (しんじょう やすし) \\
\\ 筑波大学 電子・情報 \\
In article <YAS.02Ma...@kirk.is.tsukuba.ac.jp>,
y...@is.tsukuba.ac.jp (Yasushi Shinjo) writes
>私は、C言語の const は、言語仕様上の失敗に近いかなあという
>気がします。volatile は、いいけど。
僕も同意見です。
前に「constってタイプじゃないんじゃないか」と言ったら、「read/
write でreadのみのメソッドを持つオブジェクトみたいなものだ」
と言われたことがあります。そういう意味では、確かにタイプとし
て扱うことはできると思う。
なんだけど、const ってのをタイプとしてみると、あらゆるタイプ
に直交したタイプとして現れるんですよね。それを導入すると、プ
ログラム自体の複雑さが上がるのは当然なのだと思います。
>コンパイラは、const と書いてあっても書いて同じとなると、あと
>は、const が、プログラマにとって訳に立つかです。
#define CONST_NAME 322 の代わりという意味では役に立ちますよね。
それはわかります。
でも、それ以外は、なんか偏執狂的な使い方なんだよな...
特に、ポインタの先の変更を防ぐみたいな使い方に const を
使う場合にそう感じます。
char *strcpy __P((char *, const char *));
とかって、いったい誰がどういう場合に、うれしいんでしょう?
>const ではなくて、static を拡張して、static_and_const みたい
>なものだったら、ROM化できるとか、意味がつけやすかったかなあ。
const のタイプが実体に付かないのがいけないんじゃないかなぁ。
char *p = const "string cannot be changed";
if (is_const(*p))
みたいな使い方ができるんだったら、まだ、面白かったかも。一般
的には実装できないって問題はあるけど。
でも、ハードウェア的に write protection できないのであれば、
タイプとして const を導入してもおかしくなるのは、当然だとい
う気がします。
>quick sort は、もともと関数的なアルゴリズムだから、単一代入
>の変数が出てくるんですよね。このくらいは、コンパイラが解析で
>きるでしょう。あと、単一代入という考え方はよいとしても、
>「auto 変数がスタックにある」というようなメモリの考え方と単
>一代入の考え方は馴染みません。そういう意味でも const がイマ
>イチなんだと思います。
単一代入とスタックが両立しないという考え方は直観的に正しい
気がする。なぜかは良く分からないけど。
---
Shinji KONO @ Information Engineering, University of the Ryukyus,
PRESTO, Japan Science and Technology Corporation
河野真治 @ 琉球大学工学部情報工学科,
科学技術振興事業団さきがけ研究21(機能と構成)
> でも、それ以外は、なんか偏執狂的な使い方なんだよな...
> 特に、ポインタの先の変更を防ぐみたいな使い方に const を
> 使う場合にそう感じます。
> char *strcpy __P((char *, const char *));
> とかって、いったい誰がどういう場合に、うれしいんでしょう?
確かに…
> const のタイプが実体に付かないのがいけないんじゃないかなぁ。
> char *p = const "string cannot be changed";
> if (is_const(*p))
> みたいな使い方ができるんだったら、まだ、面白かったかも。一般
> 的には実装できないって問題はあるけど。
CやC++の思想と違うよね。Javaならやってもいいかも。
> 単一代入とスタックが両立しないという考え方は直観的に正しい
> 気がする。なぜかは良く分からないけど。
それはね、スタックって「積んで、内側のインカネーションを呼んで、
戻って来た時に積んだものが同じ場所にちゃんと残っている」のがいい
わけでしょ。ところが単一代入で書き換えないとすると積む一方だから
どんどん伸ばすしかない(概念的には)。だから同じ場所にあるっていう
ことじゃなくなって、嬉しくない。
という感じがしますが… 久野
Yasushi Shinjo wrote:
> 私は、C言語の const は、言語仕様上の失敗に近いかなあという
> 気がします。volatile は、いいけど。
> (中略)
> 結局、コンパイラも人間もあんまり役には立てなくて、言語仕様と
> しても、今一つだったかなあということです。
え~と、変数のconstに関しては「同意」しますが、
関数の引数宣言では同意しかねるかな?
私は、引数の型宣言におけるconstは、関数の依存関係/並列度検出のための
役割を持たせてると勝手に思い込んでます(笑)
ただ、これを突き詰めて行くと、問題になりやすいのが、
static宣言された変数の方だったりして。
(全然、リエントラントじゃないんだもん(^^;<static変数)
と言うことで、将来に期待っ!<constの活用
In article <3C9B3DDF...@coral.ocn.ne.jp>,
Tadamasa Tamura <ta...@coral.ocn.ne.jp> writes
>私は、引数の型宣言におけるconstは、関数の依存関係/並列度検出のための
>役割を持たせてると勝手に思い込んでます(笑)
const かどうかは、最適化に関してはあんまり関係ない気がする。
定数であっても変数であってもレジスタに入れるのが今のアーキテ
クチャなので...
むしろ、alias の方が問題ですよね。自動化できない部分でもあるし。
>ただ、これを突き詰めて行くと、問題になりやすいのが、
>static宣言された変数の方だったりして。
>(全然、リエントラントじゃないんだもん(^^;<static変数)
ほとんど全部、static 宣言するってのが関数に関しては正しい
態度ですよね。変数に関しても、そうかな。
thread safe とかの問題は、static 変数は thread 毎に別に確保する
ってすれば良かったような気もする。ま、どっちもどっちかな。
Shinji KONO wrote:
> >私は、引数の型宣言におけるconstは、関数の依存関係/並列度検出の
> >ための役割を持たせてると勝手に思い込んでます(笑)
> const かどうかは、最適化に関してはあんまり関係ない気がする。
> 定数であっても変数であってもレジスタに入れるのが今のアーキテ
> クチャなので...
???
もしかして、
「スレッド分割は人間が指示しなければならない」とか、
「CPUは1個しかない」とか言った固定概念持ってます?
別のスレッドで貴兄が言っていた
> 特に、ポインタの先の変更を防ぐみたいな使い方に const を
> 使う場合にそう感じます。
>
> char *strcpy __P((char *, const char *));
>
> とかって、いったい誰がどういう場合に、うれしいんでしょう?
これは、「ポインタ先の変更を防ぐ」ではなく、
「このポインタ変数で示す内容は変更されないことを保証する」って
読めません?(まあ、普通読めないか(笑))
例えば、簡単にするためにstrcpyとstrcatだけを使いますけど、
strcpy(b,a) ; …………… (1)
strcpy(c,a) ; …………… (2)
strcat(b,d) ; …………… (3)
となっている場合、const宣言だけで以下の依存関係が導き出されます。
・(1)と(2)には依存関係が無い
・(3)は(1)の後でなければならない
よって、
(1)+(3)をCPU1に、(2)をCPU2に割り振っても、
結果は同じになるはずですよね?
これが私の言った「関数の依存関係/並列度検出」の意味です。
実際には、writeとかのシステムコールの依存性が検出できない可能性が
あるんですけどね(笑)
> >ただ、これを突き詰めて行くと、問題になりやすいのが、
> >static宣言された変数の方だったりして。
> >(全然、リエントラントじゃないんだもん(^^;<static変数)
>
> ほとんど全部、static 宣言するってのが関数に関しては正しい
> 態度ですよね。変数に関しても、そうかな。
>
> thread safe とかの問題は、static 変数は thread 毎に別に確保する
> ってすれば良かったような気もする。ま、どっちもどっちかな。
(const宣言されていない)static宣言された変数って、
そのルーチンを抜けても値を保持する関係上、
実行順序の依存性が発生しますので、thread safeにならないと思います。
と、私なりのconstへの期待でした。
In article <3C9B74E2...@coral.ocn.ne.jp>,
Tadamasa Tamura <ta...@coral.ocn.ne.jp> writes
>> char *strcpy __P((char *, const char *));
>> とかって、いったい誰がどういう場合に、うれしいんでしょう?
>例えば、簡単にするためにstrcpyとstrcatだけを使いますけど、
> strcpy(b,a) ; …………… (1)
> strcpy(c,a) ; …………… (2)
> strcat(b,d) ; …………… (3)
>となっている場合、const宣言だけで以下の依存関係が導き出されます。
>・(1)と(2)には依存関係が無い
>・(3)は(1)の後でなければならない
これって、b が実は a の変数のアドレスを指している場合、(1)
は、a のアドレスを書き換えてしまいます。これは、strcpy(&a,a)
とかの場合ですよね。strcpyだと変な感じがするけど、宣言からは
ありありです。a 自体はconstでないから、書き換えるのはokだし。
コンパイラはstrcpyだと知らないし。(知ってる奴もあるけどさ)
なので、
>・(1)と(2)には依存関係が無い
ってのを、const宣言から導出してはいけません... ってのが alias
の問題ですよね。C は、そんなのばっかです。
>これが私の言った「関数の依存関係/並列度検出」の意味です。
だったら、依存関係を明示する言語の方がいいなぁ。単一代入とか。
>> thread safe とかの問題は、static 変数は thread 毎に別に確保する
>> ってすれば良かったような気もする。ま、どっちもどっちかな。
>(const宣言されていない)static宣言された変数って、
>そのルーチンを抜けても値を保持する関係上、
>実行順序の依存性が発生しますので、thread safeにならないと思います。
thread 毎に別にすれば、そういう問題は無くなりますよね。lock
もいらないし。
ある程度回答は出したので、今回は若干チャチャ入れも~ど。
tabe wrote:
> 質問1:
> このくっ付く文字列を抑止する
> 良い方法をご存知の方教えてください。
ストリングリテラルだからくっつくのであって、
一方を変数にしてしまえば問題無し。
ということで、ファイルの先頭に
static const FILENAME = __FILE__ ;
と定義し、
printf("%s:%d %s\n",FILENAME,__LINE__,funcname);
とする。
(-Wformatより、効果低し(^^;)
また、
> char *str[] ={
> "文字列が" //ここでカンマ忘れました
> "くっ付いた"
> } ;
の対策には、
X11/Intrinsic.hから、XtNumberをかっぱらって、
数を確認するってのもありかと(笑)
ちなみに、以下の通り<XtNumber
#define XtNumber(arr) ((Cardinal) (sizeof(arr) /
sizeof(arr[0])))
上記の例では、
XtNumber(str)が、正しく','を付けていれば2に、
','を付け忘れると1になります。
これは、プリプロセッサが判断できますので、
プリプロセッサで判定文を付けておけば、
コンパイル段階で落とせます。
(ただ、数字埋めるのと何が違うと言われるとそれまでだったり(^^ゞ)
> 質問3:
> const char funcname[128] = "myfunc" ; を
> static const char funcname[] = "myfunc"
> と、staticを付けさせて、[]の128を書かせない方法
> 教えてください。
さっき、gccでやってみましたけど、
> static const char funcname[] = "myfunc" ;
って間違ってないはずですよ?
(これって、コンパイラ依存でしたっけ?)
> int func(int in)
> {
> const int new_in = in - 1; /* これは初期化 */
> 以上、constつきの自動変数の必然性の一例でした。
謎が、解けました。
私が何をわかってなかったが、解りました。
const 修飾した初期化で、
変数もありえる事を考えた事もありませんでした。
定数、リテラルによる初期化ばかり考えていたので、
自動変数として宣言したものでも、静的領域に確保して、
共有できると考えていました。
#なんで、constって名前にしたんだろう。
”読み込み専用”の意味なのだから(C-FAQ 11.8)
いっそROMって名前にすれば良かったのに。
そうすると、収容領域の誤解が発生するから、これも駄目か
佐々木さん、ありがとうございます。
簡潔な例なので、理解できました。
>
> でかいの企画 佐々木茂彦
> ssa...@dekaino.net
--
> (a) その関数の複数のインスタンスが同時に存在する
> (b) (a)のそれぞれの関数インスタンスで固有のデータ
> を生成して利用したい
> (c) (b)のデータがconstであってほしい
> という条件が成立するときですね。
この例は、
「佐々木@でかいの」さんの例で理解できました。
> > 関数の引数定義の所で、データ領域の記述が出来るのは
> > registerだけのはず。
>
> え? constも使えますが...???
K&R2 A8.6.3 関数宣言子
「パラメータの宣言指定において、許される唯一の
記憶クラスはregisterである」
データ領域の確保を強調する、以下の例なら、
ピンときたのですが。。。。
void myfunc(const struct tag hoge) /* ポインタではなく */
{
const struct tag hogehoge = hoge ;
}
>上に私が示した例は「constな
> ら自動的にstaticになる仕様のほうがよい」を否定する
> にじゅうぶんなサンプルであると思うのですけどね。
はい。じゅうぶんです。
「constな ら自動的にstaticになる仕様のほうがよい」は
以下の様に訂正します。
「const修飾されていたら、コンパイラはもっと最適化して欲しい」
例:
void myfunc()
{
const char tmp[] = __FILE__ ;
printf("%s\n",tmp) ;
printf("%s\n",tmp) ;
...
printf("%s\n",tmp) ;
}
と、プログラマが記述したら、
コンパイラは
void myfunc()
{
/* tmpは、いらない*/
printf("%s\n",__FILE__) ;
printf("%s\n",__FILE__) ;
...
printf("%s\n",__FILE__) ;
}
と解釈して欲しい。
「static」を書き損ねても、スタック領域を少し多めに使い、データをスタッ
ク領域に書き込むために少し多めの時間がかかるだけだが、そういうのはとて
も気になる(が、それらを減らすために「static」と書くのはいやだ)。
printf()の中でいろいろと大変なことをやって、スタック領域を多く使ったり、
処理時間が長くなっているかもしれないが、そういうのは気にならない。
**********************************************************************
ということですね。理解しづらい考え方ですが……。
--
N-Yas <cep0...@nyc.odn.ne.jp>
"tabe" <ta...@mug.biglobe.ne.jp> wrote in message
news:a7gn0d$nto$2...@bgsv5906.tk.mesh.ad.jp...
> 田部です。
(略)
> >上に私が示した例は「constな
> > ら自動的にstaticになる仕様のほうがよい」を否定する
> > にじゅうぶんなサンプルであると思うのですけどね。
> はい。じゅうぶんです。
> 「constな ら自動的にstaticになる仕様のほうがよい」は
> 以下の様に訂正します。
> 「const修飾されていたら、コンパイラはもっと最適化して欲しい」
> 例:
> void myfunc()
> {
> const char tmp[] = __FILE__ ;
> printf("%s\n",tmp) ;
> printf("%s\n",tmp) ;
> ...
> printf("%s\n",tmp) ;
> }
> と、プログラマが記述したら、
> コンパイラは
> void myfunc()
> {
> /* tmpは、いらない*/
> printf("%s\n",__FILE__) ;
> printf("%s\n",__FILE__) ;
> ...
> printf("%s\n",__FILE__) ;
> }
> と解釈して欲しい。
そんな風には解釈はできないんじゃないですか?
私だったら、わざわざそういう風に書いたら、
それはきっと田部さんが解釈してほしいものとは違う解釈をして
ほしいときだと思います。
というのは、私だったら、そう解釈してほしいときは
void myfunc()
{
char* tmp = __FILE___;
printf("%s\n",tmp) ;
printf("%s\n",tmp) ;
...
printf("%s\n",tmp) ;
}
と書きますので。
話題として const は無関係ないかなと。
一応、好みでアスタリスクの左右に const をつけてもいいですけど。
どちらかというと、もともと const よりstatic の話題ですよね?
__FILE__ が staticなわけですから。
以上です。
"N-Yas" <cep0...@nyc.odn.ne.jp> wrote in message
news:a7htlp$iv1$1...@nwall1.odn.ne.jp...
>
> **********************************************************************
> データを静的領域に割り当ててほしいけど、静的領域に割り当てるための指定
> 「static」は書きたくない。
ってどこで書いてます?
> 「static」を書き損ねても、スタック領域を少し多めに使い、データをスタッ
> ク領域に書き込むために少し多めの時間がかかるだけだが、そういうのはとて
> も気になる(が、それらを減らすために「static」と書くのはいやだ)。
ってどこで書いてます?
あと、こういうコードを見た事ありますか?
void func()
{
const struct tag unuse[] = {/* 昔使ってたけど今は未使用
*/
0xFF,0FF, .....................................
音声データか、なんかの初期値が
延々と続く
}
}
上記の、unuse 変数を最適化で 消去できるコンパイラは、
私の使える5種類コンパイラの中にありません。
私の見たコードでは、
const が使用されるのは
リードオンリーの表(テーブル)に多く、
「少し多めの時間」で済まない場合が多々あります。
> printf()の中でいろいろと大変なことをやって、スタック領域を多く使ったり、
> 処理時間が長くなっているかもしれないが、そういうのは気にならない。
???
http://rec.ncos.co.jp/cgi-bin/e000.cgi?183
ってな事を書いてる私がですか?
> **********************************************************************
>
> ということですね。理解しづらい考え方ですが……。
ふー。
>
> --
> N-Yas <cep0...@nyc.odn.ne.jp>―――――――――――――――――――
> > 「constな ら自動的にstaticになる仕様のほうがよい」は
> > 以下の様に訂正します。
> > 「const修飾されていたら、コンパイラはもっと最適化して欲しい」
略
> というのは、私だったら、そう解釈してほしいときは
> void myfunc()
> {
> char* tmp = __FILE___;
> printf("%s\n",tmp) ;
> printf("%s\n",tmp) ;
> ...
> printf("%s\n",tmp) ;
> }
> と書きますので。
この書き方は、
本吉さんの様にデータ領域の事を正しく知っている人の書き方です。
私の言いたかったのは、
データの割り付けを知らないプログラマが
以下のコードを書いても、
> > 例:
> > void myfunc()
> > {
;/*スタック転送命令が発生する事をプログラマ知らず */
> > const char tmp[] = __FILE__
> > printf("%s\n",tmp) ;
> > printf("%s\n",tmp) ;
> > ...
> > printf("%s\n",tmp) ;
> > }
最適化で、スタックエリアのtmp[]を消滅させて欲しい。
と言うことです。
もっと例を上げると、
void myfunc()
{
const int a = 1 ;
const int b = 2 ;
cont int c = 3 ;
printf("%d\n",a) ;
printf("%d\n",b) ;
printf("%d\n",c) l;
}
は、C++なんかでは、自動変数a,b,cは、定数値になるのでスタック消費はゼロですよ
ね。
Cだって、最適化すれば大抵、上のコードregisterか定数値になって
スタック消費はゼロになりますよね。
私のコンパイラに対する希望は
同様の最適化を
配列や、構造体の複合体でもやって欲しい。
って事です。
#あと、私はUNIX屋なで、スタック消費より速度に興味があります。
―――――――――――――――――――――――
"tabe" <ta...@mug.biglobe.ne.jp> wrote in message
news:a7icl2$2da$1...@bgsv5905.tk.mesh.ad.jp...
> 田部です。
> "Masamichi Motoyoshi" <sa...@dsl.gr.jp> wrote in message
> news:a7i9b3$m8h$1...@sv.dsl.gr.jp...
> > 本吉です。
>
> > > 「constな ら自動的にstaticになる仕様のほうがよい」は
> > > 以下の様に訂正します。
> > > 「const修飾されていたら、コンパイラはもっと最適化して欲しい」
> 略
> > というのは、私だったら、そう解釈してほしいときは
> > void myfunc()
> > {
> > char* tmp = __FILE___;
> > printf("%s\n",tmp) ;
> > printf("%s\n",tmp) ;
> > ...
> > printf("%s\n",tmp) ;
> > }
> > と書きますので。
> この書き方は、
> 本吉さんの様にデータ領域の事を正しく知っている人の書き方です。
>
> 私の言いたかったのは、
> データの割り付けを知らないプログラマが
そういうプログラマが書いたコードが
性能悪くてもしようがないのかなと思います。
> 以下のコードを書いても、
> > > 例:
> > > void myfunc()
> > > {
> ;/*スタック転送命令が発生する事をプログラマ知らず */
> > > const char tmp[] = __FILE__
> > > printf("%s\n",tmp) ;
> > > printf("%s\n",tmp) ;
> > > ...
> > > printf("%s\n",tmp) ;
> > > }
>
> 最適化で、スタックエリアのtmp[]を消滅させて欲しい。
> と言うことです。
ここでスタック上にtmpをおかないように最適化するためには
コンパイラが printf の動作を知っている必要があると思いますけどね。
> もっと例を上げると、
> void myfunc()
> {
> const int a = 1 ;
> const int b = 2 ;
> cont int c = 3 ;
> printf("%d\n",a) ;
> printf("%d\n",b) ;
> printf("%d\n",c) l;
> }
> は、C++なんかでは、自動変数a,b,cは、定数値になるのでスタック消費はゼロです
よ
> ね。
> Cだって、最適化すれば大抵、上のコードregisterか定数値になって
> スタック消費はゼロになりますよね。
そのコードでいえば、const つけなくても
最適化されて、スタック消費量はゼロになります。
Cでも。
なぜ、C++に限定するのかわかりませんけど。
逆に、const つけても
printf("%p\n", &a)
と書けば、通常の処理系ではスタック上に変数aの実体がおかれると思います。
なぜなら、いかに const をつけようとも変数は変数でしかないので
アドレスを持つことは誰も否定できないですが、
定数やレジスタは通常はアドレスを持たないので。
先の
const char tmp [] = __FILE__;
がスタック上に実体がおかれるのも
同じ理由だと思っているのですけどね。
tmp[]はauto変数で、そのアドレスは
tmpで参照できるってことです。
以上です。
**********************************************************************
データがスタック領域に割り当てられると、スタック領域を少し多めに使い、
スタック領域に書き込むために時間が少し多めにかかるのがとても気になるの
で静的領域に割り当てたいのだが、いちいち「static」と書くのは面倒なので、
書かなくても静的領域に割り当てるように改良してほしい。
**********************************************************************
というようになると思いますが違いますか?
At Fri, 22 Mar 2002 00:12:34 +0900,<a7ctjf$h2u$1...@bgsv5906.tk.mesh.ad.jp>
tabe wrote:
>
> 書き換えては駄目のconstオブジェクトを、
> わざわざ、書き換え可能なスタック領域にコピーしなければならない
> 必然性が私には解らない。
必然性が私にはわからないから静的領域に割り当てるようにしてほしい、とい
うのではダメですね。必然性があろうとなかろうと、データをスタック領域に
割り当てるのが間違いというわけではないのですから。
At Sun, 24 Mar 2002 01:27:09 +0900,
tabe wrote:
>
> 私の見たコードでは、
> const が使用されるのは
> リードオンリーの表(テーブル)に多く、
> 「少し多めの時間」で済まない場合が多々あります。
そうした場合は「static」と書けばいい、というだけのことだと思いますが、
違うのですか?
--
N-Yas <cep0...@nyc.odn.ne.jp>
"N-Yas" <cep0...@nyc.odn.ne.jp> wrote in message
news:a7jqka$1i7u$1...@nwall1.odn.ne.jp...
> tabe wrote:
> > 私の見たコードでは、
> > const が使用されるのは
> > リードオンリーの表(テーブル)に多く、
> > 「少し多めの時間」で済まない場合が多々あります。
>
> そうした場合は「static」と書けばいい、というだけのことだと思いますが、
> 違うのですか?
回答
「対処」はこれで良いです。
static を書き忘れたら、staticを書けば良い。
カンマを書き忘れたら、カンマを書けば良い。
変数の初期化を忘れたら、初期化すれば良い。
+=と、+を間違えたら、+=と書けば良い。
プログラムがBUGたら、BUGを直せば良い。
#この回答前もしたな。。。。
「予防」をどうするかです。
static を書き忘れないためにはどうしたらよいか?
static を知らない人にはどう教えるか?
試しに、%grep static *.h と ヘッダファイルから static を検索して見て
ください。
何も検出されなければ、OK
何か検出されたら要検討。
static func(void) ; のプロトタイプ宣言とか、
stattic struct tag hoge = { の変数の初期テーブルとか、
> 田部さんの希望を、コンパイラをつくっている人たちに伝えるとしたら、どの
> ように伝えるのでしょうか。
> **********************************************************************
> データがスタック領域に割り当てられると、スタック領域を少し多めに使い、
> スタック領域に書き込むために時間が少し多めにかかるのがとても気になるの
> で静的領域に割り当てたいのだが、いちいち「static」と書くのは面倒なので、
> 書かなくても静的領域に割り当てるように改良してほしい。
> **********************************************************************
>
> というようになると思いますが違いますか?
回答:
「const修飾されていたら、コンパイラはもっと最適化して欲しい」って
前書いてますけど。
>
> At Fri, 22 Mar 2002 00:12:34 +0900,<a7ctjf$h2u$1...@bgsv5906.tk.mesh.ad.jp>
> tabe wrote:
> >
> > 書き換えては駄目のconstオブジェクトを、
> > わざわざ、書き換え可能なスタック領域にコピーしなければならない
> > 必然性が私には解らない。
>
> 必然性が私にはわからないから静的領域に割り当てるようにしてほしい、とい
> うのではダメですね。必然性があろうとなかろうと、データをスタック領域に
> 割り当てるのが間違いというわけではないのですから。
回答:
はい。
間違いでありません。
「無駄では無いか?」って言ってます。
例:
最適化前:
int myfunc(int id)
{
const char fname[1024] = __FILE__ ;
char output[1024] ;
switch(id) {
case 1: strcpy(output,"壱") ;break ;
case 2: strcpy(output,"弐");break ;
case 3: strcpy(output,"参");break ;
}
printf("%s:%s\n",fname,output) ;
}
最適化後(コンパイラはこう解釈して欲しい):
int myfunc(int id)
{
register const char* const fname = __FILE__ ;
register char *output ;
switch(id) {
case 1: output="壱"; break ;
case 2: output="弐"; break ;
case 3: output="参"; break ;
}
printf("%s:%s\n",fname,output) ;
}
要は、
「文字列リテラルを直接見るコードを生成してよ」
って事です。
> -- --
> > 最適化で、スタックエリアのtmp[]を消滅させて欲しい。
> > と言うことです。
>
> ここでスタック上にtmpをおかないように最適化するためには
> コンパイラが printf の動作を知っている必要があると思いますけどね。
いいえ、必要ありません。
> そのコードでいえば、const つけなくても
> 最適化されて、スタック消費量はゼロになります。
> Cでも。
> なぜ、C++に限定するのかわかりませんけど。
C-FAQ 11.8
> 定数やレジスタは通常はアドレスを持たないので。
> 先の
> const char tmp [] = __FILE__;
> がスタック上に実体がおかれるのも
> 同じ理由だと思っているのですけどね。
ちょと違うと思います。
文字列リテラルはアドレスを持ちます。
コンパイラの実装にもよりますが、
自動変数の、
const char tmp [] = __FILE__;
を実現するには、
コンパイラの生成コードのイメージとして、
strcpy(スタックエリア文字列、静的エリア文字列) ;
で、実現している物が多いです。
> > char *strcpy __P((char *, const char *));
> > とかって、いったい誰がどういう場合に、うれしいんでしょう?
>
> 確かに…
昔まだ「bcopy と memcpy, どっちがどっちだったっけ?」とかいってた頃は
ヘッダファイルに随分お世話になったんですが….
田部> いいえ、必要ありません。
例:(コンパイラはこう解釈して欲しい):
void myfunc()
/* const 変数の 右辺が文字列リテラルの場合、 */
/* それを「べた」で使う */
/* もしくは、 いったん register const char * に入れて使う */
printf("%s\n",__FILE__) ;
printf("%s\n",__FILE__) ;
...
printf("%s\n",__FILE__) ;
}
以下の様な最適化をするには、
コンパイラが,strcpy がなんであるか
知っている必要があります。
#gcc等は、知っています。
例:
最適化前:
int myfunc(int id)
{
const char fname[1024] = __FILE__ ;
char output[1024] ;
switch(id) {
case 1: strcpy(output,"壱") ;break ;
case 2: strcpy(output,"弐");break ;
case 3: strcpy(output,"参");break ;
}
printf("%s:%s\n",fname,output) ;
}
最適化後(コンパイラはこう解釈して欲しい):
int myfunc(int id)
{
register const char* const fname = __FILE__ ;
register char *output ;
switch(id) {
case 1: output="壱"; break ;
case 2: output="弐"; break ;
case 3: output="参"; break ;
}
printf("%s:%s\n",fname,output) ;
}
―――――――――――――――――――――
「予防」はしなくてもいいと思います。
「static」を書いてないから遅い、書けばもっとはやくなると思ったら書けば
いいし、そう思わなければ書かなくてもかまわないでしょう。
書き忘れたからといって動作がおかしくなるわけではないのですから。
> > 田部さんの希望を、コンパイラをつくっている人たちに伝えるとしたら、どの
> > ように伝えるのでしょうか。
> > **********************************************************************
> > データがスタック領域に割り当てられると、スタック領域を少し多めに使い、
> > スタック領域に書き込むために時間が少し多めにかかるのがとても気になるの
> > で静的領域に割り当てたいのだが、いちいち「static」と書くのは面倒なので、
> > 書かなくても静的領域に割り当てるように改良してほしい。
> > **********************************************************************
> >
> > というようになると思いますが違いますか?
> 回答:
> 「const修飾されていたら、コンパイラはもっと最適化して欲しい」って
> 前書いてますけど。
それでは、「最適化」してほしい理由が分かりません。
「最適化」してほしい理由は、私が言ったようなことでしょう?
> 間違いでありません。
> 「無駄では無いか?」って言ってます。
無駄だとしても、その無駄が気にならなければ「最適化」してほしいとは思わ
ないでしょう。
田部さんは「最適化」によって短くなるわずかな時間がとても気になるから
「最適化」してほしいと思うのですね?
--
N-Yas <cep0...@nyc.odn.ne.jp>
> 以下の様な最適化をするには、
> コンパイラが,strcpy がなんであるか
> 知っている必要があります。
> #gcc等は、知っています。
gccはbuild-in関数としてstrcpy()を持っているだけです。
> 例:
> 最適化前:
> int myfunc(int id)
> {
> const char fname[1024] = __FILE__ ;
> char output[1024] ;
> switch(id) {
> case 1: strcpy(output,"壱") ;break ;
> case 2: strcpy(output,"弐");break ;
> case 3: strcpy(output,"参");break ;
> }
> printf("%s:%s\n",fname,output) ;
> }
> 最適化後(コンパイラはこう解釈して欲しい):
> int myfunc(int id)
> {
> register const char* const fname = __FILE__ ;
> register char *output ;
> switch(id) {
> case 1: output="壱"; break ;
> case 2: output="弐"; break ;
> case 3: output="参"; break ;
> }
> printf("%s:%s\n",fname,output) ;
> }
仮に__FILE__ マクロの文字列リテラルの長さが10だっとして
最適化前の例では fname[12]とかfname[100]の値は\0ですが、
最適化後の例は、ではfname[12]にアクセスするする操作が
未定義になります。
printf()がそのような操作をしないとコンパイラが知らないと
この最適化を行うことは出来ません。
実現するには、広い範囲で意味解釈を行う必要があり、
プログラマが正しい知識を持っていれば不要な最適化など、
害ばかりで益なし、コンパイラのバグの元になるだけなので
わたし個人的にはやめて欲しいです。
constつければROM化領域に入るとか、file scopeのことをmodule内と呼ぶとか
ITRON環境ローカルな知識にこりかたまってるプログラマにしかうれしくない
最適化ですよね。
でかいの企画 佐々木茂彦
ssa...@dekaino.net
# コードは若干省略します。
-----------------------------------------------------------------------
static const char* _filename;
static unsigned long _linenumber;
void _debugf(char* fmt, ...)
{
printf("%s:%d ", __filename, __linnumber);
vprintf(...);
}
#define debugf _filename = __FILE__ , _linenumber = __LINE__ , _debugf
-----------------------------------------------------------------------
int myfunc(void)
{
debugf("myfunc");
}
-----------------------------------------------------------------------
Visual C++ にある TRACE と似たようなもんですが、これなら間違いを出来
るだけ無くせるかとおもふ。
tabeさんの<a77lkg$flc$1...@bgsv5905.tk.mesh.ad.jp>から
>田部です
>int myfunc(void)
>{
> conts char funcname[128] = "myfunc" ;
> printf("%s:%d\t%s" __FILE__,__LINE__,funcname) ;
>}
>このBUGの逆版もあり、
> printf("%s:%d\t%s",__LINE__ , __FILE__,funcname) ;
>}
(snip)
--
toys mailto:<toys...@hotmail.com>
int funcConst(const char* str)
{
const char* _str;
_str = str;
}
こういうのと
int funcStatic(const char* str)
{
static const char* _str;
_str = str;
}
これだと、やっぱり意味合いが違うから、static と const は区別してるん
じゃないですか?
C++ の class でも同様に
class foo
{
const char* m_const_str;
// クラスのメンバー内にインスタンシエートされる。
static const char* m_static_str;
};
static const char* foo::m_static_str;
// グローバルにインスタンシエートしないとだめ。
と、存在している場所が違う。
constは型をさしてstaticは置き場所(スコープ範囲)な訳ですから、自動
的に型が、constだからってスコープ範囲はstaticってするのは間違いを増や
す原因になると思う。デフォルトは、autoなんだからとりあえず、みんなデフ
ォルトは、autoにしないとまずいわけですし。
>識者の皆様に質問3:;
> const char funcname[128] = "myfunc" ;
> を
> static const char funcname[] = "myfunc"
> と、staticを付けさせて、[]の128を書かせない方法
> 教えてください。
# 返答にはなりませんが
?? = "myfunc";
?? には何が渡されるのか、よくわかりませんが、この"myfunc"って実際に
はプログラムが立ち上がった時点でスタック内(制定な領域に?)に用意されて
る?(憶測ですが)
"myfunc" の返り血は、static char* だから指定しなくても良いんじゃない
かな?なんて思ったりする。
--
toys mailto:<toys...@hotmail.com>
> > > そうした場合は「static」と書けばいい、というだけのことだと思いますが、
> > > 違うのですか?
> > 回答
> > 「対処」はこれで良いです。
> > 「予防」をどうするかです。
>
> 「予防」はしなくてもいいと思います。
あーあ、言いきっちゃった。
「BUGが出たら、BUGを直せば良い。」
と、お考えですね。
私の考えは、
「BUGは出ないようにすれば良い」です。
> 「static」を書いてないから遅い、書けばもっとはやくなると
> 思ったら書けばいいし、
> そう思わなければ書かなくてもかまわないでしょう。
> 書き忘れたからといって動作がおかしくなるわけではないのですから。
「おかしく」なりますよ。
C-FAQ 16.3http://www.catnet.ne.jp/kouno/c_faq/c16.html#0
で示されている様にクラッシュすることがあります。
Faqになるくらい、頻繁におきてるって事です。
> > > 田部さんの希望を、コンパイラをつくっている人たちに伝えるとしたら、どの
> > > ように伝えるのでしょうか。
> > > **********************************************************************
> > > データがスタック領域に割り当てられると、スタック領域を少し多めに使い、
「スタック領域を少し」で、すまない
数千BYTEを一気に消費して、
スタックオーバーフローの危機に直面する例を
すでに提示しています。
> > > スタック領域に書き込むために時間が少し多めにかかるのがとても気になるの
「時間が少し」かどうかは、
"N-Yas" 殿のビジネス的判断に委ねますが
3倍処理時間が遅くなっている例を
すでに提示しています。
> > > で静的領域に割り当てたいのだが、
> > > いちいち「static」と書くのは面倒なので、
> > > 書かなくても静的領域に割り当てるように改良してほしい。
> > > **********************************************************************
ここは、私にも誤解があり太田氏に指摘されているので、
#私の一番の認識不足は、
# const 変数の = の右辺に変数が記述できる事を認識していなかったので、
#「const が来たら一律 static に出来る」の私の初期の主張は誤りです。
#誤りはすでに、認めています。
以下現在の主張を
出来るだけ、わかりやすく書きますね。
void func()
{
const char buf[] = "abc" ;
}
の様な、自動変数配列を文字列リテラルで初期化するには
コンパイラの実装方法にも依存しますが、
主に2つの方法が考えられます。
(1) 一度静的エリアに文字列リテラルをとっておいて、
関数に突入した時に、
自動変数エリアにコピーする方法。
イメージ的には
strcpy(自動変数エリアのbuf、静的エリア文字列リテラル) ;
(2) 関数に突入した時に、
buf[0] ='a' ;
buf[1] ='b' ;
buf[2] ='c' ;
buf[3] ='\0' ;
を実行する方法。
で、今考えているのは、
(1)の方法で実装されている場合、
どうせ、すでに 「静的エリアに文字列リテラル」があるんだから
これを直接みればいいじゃないか。
って考えです。
> > > というようになると思いますが違いますか?
> > 回答:
> > 「const修飾されていたら、コンパイラはもっと最適化して欲しい」って
> > 前書いてますけど。
>
> それでは、「最適化」してほしい理由が分かりません。
> 「最適化」してほしい理由は、私が言ったようなことでしょう?
以上、「最適化」してほしい理由は、
(1) 処理速度を早くしたい。
(2) 無駄なメモリは使いたくない。
>
> > 間違いでありません。
> > 「無駄では無いか?」って言ってます。
>
> 無駄だとしても、その無駄が気にならなければ
「無駄が気にならない」開発現場なんですね?
> 「最適化」してほしいとは思わないでしょう。
> 田部さんは「最適化」によって短くなるわずかな時間が
私の経験則でよければ、
最適化すると、処理速度は約30~40%UPします。
30~40%UPが、
わずかな時間かどうかは、ビジネス的局面に依存します。
2秒が1秒になった =>意味無し(リアルタイム系は別?)
2時間が1時間になった =>おお!!
> とても気になるから「最適化」してほしいと思うのですね?
「気になる」でなくて、
私の開発環境では、「遅いのは許されない」です。
――――――――――――――――――――――
御意。しかしながら、それでもバグは出るものなのです。
# バグじゃない不具合ってのもあるし。
--
red brick
> void func()
> {
> const char buf[] = "abc" ;
> }
buf[] の初期化は func 呼び出しと一対一関係にないといけない, と規格にあ
ります (私も以前片山さんに指摘されました).
6.2.4 Storage durations of objects
...
[#4] An object whose identifier is declared with no linkage
and without the storage-class specifier static has automatic
storage duration.
...
6.8 Statements and blocks
...
[#3] A block allows a set of declarations and statements to
be grouped into one syntactic unit. The initializers of
objects that have automatic storage duration, and the
variable length array declarators of ordinary identifiers
with block scope, are evaluated and the values are stored in
the objects (including storing an indeterminate value in
objects without an initializer) each time the declaration is
reached in the order of execution, as if it were a
statement, and within each declaration in the order that
declarators appear.
定数にしちゃうと次の関数の出力が常に一定になっちゃうわけですよね.
void
foo (int n)
{
const char buf[] = "abc";
if (--n < 0)
return;
printf ("%p\n", buf);
foo (n);
> >・(1)と(2)には依存関係が無い
>
> ってのを、const宣言から導出してはいけません... ってのが alias
> の問題ですよね。C は、そんなのばっかです。
以前も話題に出しましたが, restrict ってのが導入されています.
6.7.3.1 Formal definition of restrict
...
[#7] EXAMPLE 1 The file scope declarations
int * restrict a;
int * restrict b;
extern int c[];
assert that if an object is accessed using one of a, b, or
c, and that object is modified anywhere in the program, then
it is never accessed using either of the other two.
[#8] EXAMPLE 2 The function parameter declarations in the
following example
void f(int n, int * restrict p, int * restrict q)
{
while (n-- > 0)
*p++ = *q++;
}
assert that, during each execution of the function, if an
object is accessed through one of the pointer parameters,
then it is not also accessed through the other.
で, 今時の strcpy のプロトタイプ宣言はこうです.
char *strcpy(char * restrict s1,
const char * restrict s2);
????const ???????????????????????????
???????????????
int foo(char* hoge);
???????????? hoge ????????????????????
?????????????????????????????
bar(const char* gege)
{
char buf[256];
strcpy(buf, gege);
foo(buf);
....
}
??????????????
int foo(const char* hoge);
???????????????????????????????????
?????
??????????????????……?
--
???
naga...@csf.ne.jp
どうしてそう思うのでしょうか。
staticであるべきものにstaticを付け忘れた場合の話ですよね...?
> 私の考えは、
> 「BUGは出ないようにすれば良い」です。
そりゃそうですけど、N-Yasさんは、この件に関してそういう努力
をする価値はないといってるのだと思うのですが。(私もそう思い
ます)(あ、違ってたらすみません)
# BYTEなんていうのこそ予防してほしい(笑)
田部さんはここを読んでいる人に何を求めているのでしょうか。
--
おかはな
初期化データが多いと思ったら「static」と書けばいいというだけの話ですね。
その C-FAQ 16.3にも「大きな配列を使うときはstaticと宣言したほうがいい」
と書かれているわけですし。
> 「スタック領域を少し」で、すまない
> 数千BYTEを一気に消費して、
> スタックオーバーフローの危機に直面する例を
> すでに提示しています。
田部さんの言う「最適化」はスタックオーバーフローを防ぐのにも役立つ、と
いうことですか?
At Sun, 24 Mar 2002 01:27:09 +0900,<a7ianb$10n$1...@bgsv5905.tk.mesh.ad.jp>
tabe wrote:
>
> void func()
> {
> const struct tag unuse[] = {/* 昔使ってたけど今は未使用
> */
> 0xFF,0FF, .....................................
> 音声データか、なんかの初期値が
> 延々と続く
> }
> }
この場合なら、「最適化」でスタックオーバーフローを防げるでしょうけど、
unuse[]が「const」なしで定義されていたら、「最適化」の対象にならないの
でスタックオーバーフローは防げません。
> (1)の方法で実装されている場合、
> どうせ、すでに 「静的エリアに文字列リテラル」があるんだから
> これを直接みればいいじゃないか。
> って考えです。
だからそれは、
static const char buf[] = "abc" ;
のように「static」をつければいいだけでしょう?
どうしてその程度のことを避けようとするのですか?
> 私の経験則でよければ、
> 最適化すると、処理速度は約30~40%UPします。
At Sat, 23 Mar 2002 10:43:35 +0900,<a7gn0d$nto$2...@bgsv5906.tk.mesh.ad.jp>
tabe wrote:
>
> void myfunc()
> {
> const char tmp[] = __FILE__ ;
> printf("%s\n",tmp) ;
> printf("%s\n",tmp) ;
> ...
> printf("%s\n",tmp) ;
> }
この関数に田部さんの言う「最適化」をすると処理速度が30~40%アップする
のですか?
--
N-Yas <cep0...@nyc.odn.ne.jp>
<a7mqpq$f87$1...@news2.rim.or.jp>の記事において
doh...@hf.rim.or.jpさんは書きました。
> In article <a7mmq6$f5r$1...@bgsv5905.tk.mesh.ad.jp>
> "tabe" <ta...@mug.biglobe.ne.jp> writes:
>
> > void func()
> > {
> > const char buf[] = "abc" ;
> > }
>
> buf[] の初期化は func 呼び出しと一対一関係にないといけない, と規格にあ
> ります (私も以前片山さんに指摘されました).
:
> 定数にしちゃうと次の関数の出力が常に一定になっちゃうわけですよね.
>
> void
> foo (int n)
> {
> const char buf[] = "abc";
> if (--n < 0)
> return;
> printf ("%p\n", buf);
> foo (n);
> }
80 - 90 % ANSI C の CINT だとこれ出力が一定になるんですが、
void tarfu(char bar[],int count) {
bar[4] = count+bar[4];
}
void foo(int i) {
const char bar[] = "hoge0"; // ‡
tarfu((char *)bar, i); // †
if ( i > 0 ) {
foo(--i);
}
printf("%p\n", bar);
}
だと変るです。まぁ、†が何考えてるかなぁ~なところはありますが。
ちなみに、これで‡を static 付きに解釈しちゃうと、FreeBSD 4.4R の
gcc 2.8.1 だと死にます。.rodata にリテラル "hoge0" が置かれて、そ
れに直に tarfu(...) で書き込みに行っちゃうので。
# もちろん gcc はそんな解釈しないので、死なない。
で、通常でかい固定データをローカルに持ち込むなら const 以前に
static するはずなので、const が付いているかどうかを問題にする以前
の話のような。
上の変態コードも規格上はエラーにならんので、const だけだったら
static に勝手になっちゃうのは、やっぱり余計なお世話な気がするです。
これが「static にならんのはけしから~ん!」というなら、それ以前に
「†のキャストは絶対まかりなら~ん!」と言ってくれないと変な気が
するです。
キャストがあるかぎり、コンパイラにとって安心して static にしちま
えないってぇ状況がいくらでもありそうだから、端っから責任持てない
ことは手を染めないのがよろしいってことですね。
# static が存在しないなら事情は別ですけれど。
--
成田 隆興 @ エー・アイ・ソフト株式会社ソリューシュン開発部
E-mail tak...@aisoft.co.jp
『十分間で決断し、短い理由を添えよ。』
In article <a7mrhk$fhi$1...@news2.rim.or.jp>,
doh...@hf.rim.or.jp (Kazuo Fox Dohzono) writes
>で, 今時の strcpy のプロトタイプ宣言はこうです.
> char *strcpy(char * restrict s1,
> const char * restrict s2);
なるほど。確かに、Linuix 2.0ではそうなっているな。知りませんでした。
段々ぱっと見で、意味がわからなくなってきますね。こういう解決方法
が正しいのかなぁ。C 自体が正しい解決方法ではないから、こうなって
しまうんでしょうね。
---
Shinji KONO @ Information Engineering, University of the Ryukyus,
PRESTO, Japan Science and Technology Corporation
河野真治 @ 琉球大学工学部情報工学科,
科学技術振興事業団さきがけ研究21(機能と構成)
規格には逆らえません。
(1) const と来たらstatic にしてしまえも
(2) 最適化で、const なら 自動変数初期値のリテラル値を共有してしまえも
取り下げます。
勉強になりました。
"Narita Takaoki" <tak...@aisoft.co.jp> wrote in message
news:a7n6uk$35l$1...@nwall2.odn.ne.jp...
本当は色々と答え用意しておいたんですが、話があまり建設的では
なくなりそうなので、こちらに相乗り(^^;
Shinji KONO wrote:
> >で, 今時の strcpy のプロトタイプ宣言はこうです.
> > char *strcpy(char * restrict s1,
> > const char * restrict s2);
(中略)
> こういう解決方法が正しいのかなぁ。
正しいか正しくないかと言われると、ある側面では正しいが、
別の側面から見ると正しくないってのが本当のところでしょう。
実際、書き方の美しさや見やすさと言う点では、他にわかり易い言語は
いくらでもあるでしょうし、今後も出てくるでしょう。
(「並列オブジェクト指向言語」は河野先生の研究テーマでもあること
ですし…………)
では、なぜ未だにCが生き長らえるのですか?
それが、
> C 自体が正しい解決方法ではないから、こうなってしまうんでしょうね。
に対する本質的な答えだと私は思います。
Cが他の言語に比べて優位な点としては、とりあえず、以下の点が
思いつきます。(他にあるかもしれないけど許して(((((^^;)
(1)コード効率の高さ(ソースに書かれたこと以外は一切しない)
(型変換は別問題ね(^^;<ソースに書かれたこと以外)
(2)言語としての単純さ(これは、コンパイラの移植性に影響)
(3)他プラットフォームへの移植の容易さ(これは、gccの存在が大きい)
(4)高級言語並の記述のし易さ
これらの事が、各方面でCが利用される理由だと思います。
(私個人にとっては(1)が一番重要(^^ゞ)
研究レベルの問題としては、どうということはないでしょうが、
商業レベルにおいては、これらは非常に重要な意味を持ちます。
特に商業レベルの場合は、必ずしも「完全である」ことまでは
要求されません。
確かに理想ではありますが、人間が作る以上、ドコかに矛盾があっても
おかしくないでしょうし、使う側もその矛盾に対し制約を与えても、
それに勝るメリットがあるのであれば、割り切って使います。
(この良い例が、Spec-CとかSystemCでしょう。
知らない場合は、検索エンジンを使用するなりしてみてください。
お近くにいるはずの和田教授に聞いてみても判るかもしれません。
「なんでこんなものをそんな用途に使うんだ~!?」と思うはずです……
って言うより、私も未だに「そこまで制約したら意味無いやん」と
思いつつも、使わないといけないんだろうなぁと思ってます。)
だからこそCは、既存のコードの延命も図りつつも、「つぎはぎ」と
いわれようと、完全ではないと判りつつも、並列化への道を
模索しているのだと私は思います。
(だから私は最初に「と言うことで、将来に期待っ!<constの活用」と
書きました。)
ではでは~~~~~(^^/
<a7na8a$fcn$1...@bgsv5906.tk.mesh.ad.jp>の記事において
ta...@mug.biglobe.ne.jpさんは書きました。
> わかりました。
>
> 規格には逆らえません。
> (1) const と来たらstatic にしてしまえも
> (2) 最適化で、const なら 自動変数初期値のリテラル値を共有してしまえも
> 取り下げます。
ん~、別に規格に逆らっちゃ駄目ってわけでもなくて、駄目な規格だっ
たら駄目と言うべきで。ただし、どう駄目でどうすると良くなるっての
は、明示するべきでしょうね。
あと、今回の件を納得するにしても規格だからじゃなくて、どうしてそ
うなっているかまで掘り下げた上で納得しないと、法の精神をほかして
する法解釈みたいになるので、あんまり歓迎できないことかと。
で、今回のみそはやっぱり
1.既に例示したようなダメダメなキャストが出来る
2.ローカル変数に対する const と static の関係は 1 がある
かぎり推定不可
なのではないかと。じゃあダメダメキャストを無くせばって説が出るわ
けだけど、そうしたら C 言語の良いところも削がれそうだし、個人的に
は C 言語からそれがなくなったらつまらない。(^^;;;
# ダメダメな例は、
# const char foo[] = "snafu";
# char *p = (char *)foo;
# でも良いですね。宣言で一所懸命安全にしようったってキャストがあ
# るかぎり、そうは問屋は卸さないっつぅか、フランス代表に攻められ
# る日本代表のラインディフェンスよりよわよわっつぅか(その心は、な
# んぼでも裏をかける。^^;;;;)。
で、C++ に言及しておくと、C のダメダメキャストはまだ愉快に思える
範疇だけれど、このダメダメキャストとポインターと C++ のダメダメク
ラスの仕組み(継承云々含めて)とが組み合わさるとダメダメの8乗くらい
な感じになって、「ラスボスがしばらく無敵状態です」みたいになるの
で、さすがに個人的にも勘弁信濃の善光寺。(^^;;;;;;;
規格はともかくとして、なぜこのようなコードを使いた
いのか、私にはよく理解できませんでした。
考えられるとしたら
(a) 文字列定数に“名前”を付けて即値でのアクセスを
禁止したい
(b) 同じ文字列定数が複数箇所に出てくるのでそれらが
占有する領域を共有したい
ぐらいかな?
(a)に関しては、enumで文字列定数名を宣言できない以
上、「名前空間だけ消費して領域は占有しない」ような
方法はないわけですよね。そういう認識からスタートす
るとして、じゃあ上のようなコードでそれを代用したい、
と思ったとしても、それがうまくいかないとわかったら
何か別の方法を模索するのがふつうでしょう。自分の目
論みが通らないのをconstの仕様のせいにする了見がわ
からない...。
(b)に関しては、同じ文字列定数が複数出現したら(まっ
たく同じでなくても"abc"と"bc"のように末尾側が部分
一致するなら)、いまどきのコンパイラーならそれをま
とめてひとつの領域に格納してくれますよね。だったら
それも上のようなコードを書く理由にはならない...。
いずれにしても、「遅いのは許されない」のなら「デー
タの割り付けを知らないプログラマ」などを使うわけに
はいかないと思うのですが、違うのかな。どうも私には
田部さんのバランス感覚がちょっとずれているように見
えるのですが。
--
太田純(Junn Ohta) (株)リコー/新横浜事業所
oh...@sdg.mdd.ricoh.co.jp
> いずれにしても、「遅いのは許されない」のなら「デー
> タの割り付けを知らないプログラマ」などを使うわけに
> はいかないと思うのですが、違うのかな。
「遅いのは許されない」場合でも、
「デー タの割り付けを知らないプログラマ」や、
「時間が少し多め」とかいってるプログラマを
使って仕事をするのが現実です。
> どうも私には
> 田部さんのバランス感覚がちょっとずれているように見
> えるのですが。
だから、
%grep static *.h
って、打ってくれれば僕の言ってる意味解りますって。
#太田さんの書いたソースコード以外じゃないと駄目ですよ。
―――――――――――――――――――
あと、補足ですけど、
#完全主義者の、こんこんちきって、思われかれない発言をしてるので。
lintの警告を全部つぶせ、とか、
gcc -Wall -W -Oの警告を全部つぶせ、とか
僕は言ってませんよ。
ほどほど、つぶせって、言ってますけど。
#また、誤解を招くかな。
だから、打て!!!!!!!!
> 田部です
> "Tomoaki NISHIYAMA" <tom...@nibb.ac.jp> wrote in message
> news:86y9gf30...@koke.nibb.ac.jp...
> > > 田部です。
> > > だから、
> > > %grep static *.h
> > > って、打ってくれれば僕の言ってる意味解りますって。
> > grep static *.h
> > でほとんど何もでないのは当たり前じゃないですか?
> > ふつうstaticってヘッダファイルに書かないと思いますけどね。
> > 関数の実体を定義しているファイルに書くだけでいいはずでしょう。
>
> だから、打て!!!!!!!!
一体、どこで打てば分かるのかを説明して頂きませんとわかりません。
static inline func()がかかったり、関数の実体定義が含まれている
header fileで帰り値にそこへのポインターを返している例以外は
今のところ発見できていません。
> 一体、どこで打てば分かるのかを説明して頂きませんとわかりません。
> static inline func()がかかったり、関数の実体定義が含まれている
> header fileで帰り値にそこへのポインターを返している例以外は
> 今のところ発見できていません。
/usr/includeとかの下で
grepしてもこの話の面白さは解らないんだ。
自分たちで作ったプログラムの
ヘッダファイルから
static を検索して下さい。
何も見つからなければ、
tomoakiさんと、
教授が優秀って事です。
#スコープルールがちゃんと解っているって事です。
あと、
static char sccsid[] = "なんとか" ;
static char cvsid[] = "こんとか" ;
ってのがあっても、無視してOK。
ということなら、constをstatic constにしたくらいで
はちっとも安心できなくて、安心できるくらいのチェッ
クを行うのなら逆にconstをstatic constにしてすます
程度の逃げなんてまったく不要になりそうなものです。
つまり、(ほかのデメリットがない状況で言語規約上も
問題ないとして)constを処理系がstatic constに読み替
えてくれてもとりたててうれしいとは感じない、という
人がほとんどのような気がするんですね。
> 「遅いのは許されない」場合でも、
> 「デー タの割り付けを知らないプログラマ」や、
> 「時間が少し多め」とかいってるプログラマを
> 使って仕事をするのが現実です。
「現実」を受け入れるなら、その「現実」が許す範囲で
しか「遅いのは許されない」などとは言ってられないで
しょう?
「現実」が厳しいのであれば「遅いのは許されない」と
いうのも絵に描いた餅でしかない。私からみればconst
をstatic constに読み替えてくれる処理系も現実の餅を
作り出してはくれないわけです。
> だから、
> %grep static *.h
> って、打ってくれれば僕の言ってる意味解りますって。
> #太田さんの書いたソースコード以外じゃないと駄目ですよ。
ええと、何かフリーソフトのソースで具体例として適切
なものを挙げてみていただけますか?
"tabe" <ta...@mug.biglobe.ne.jp> wrote in message
news:a7q4li$619$1...@bgsv5905.tk.mesh.ad.jp...
> 田部です。
> "Tomoaki NISHIYAMA" <tom...@nibb.ac.jp> wrote in message
> news:86vgbj2y...@koke.nibb.ac.jp...
> > "tabe" <ta...@mug.biglobe.ne.jp> writes:
> > > だから、打て!!!!!!!!
> あ。
> ごめん、ごめん。
> tom...@nibb.ac.jp さんは、ac.jpだから
> 学生さんだね。
>
> > 一体、どこで打てば分かるのかを説明して頂きませんとわかりません。
> > static inline func()がかかったり、関数の実体定義が含まれている
> > header fileで帰り値にそこへのポインターを返している例以外は
> > 今のところ発見できていません。
>
> /usr/includeとかの下で
> grepしてもこの話の面白さは解らないんだ。
>
> 自分たちで作ったプログラムの
> ヘッダファイルから
> static を検索して下さい。
> 何も見つからなければ、
> tomoakiさんと、
> 教授が優秀って事です。
> #スコープルールがちゃんと解っているって事です。
C言語に static というキーワードがあることを
知らないだけという説もあると思いますけどね。
> あと、
> static char sccsid[] = "なんとか" ;
> static char cvsid[] = "こんとか" ;
> ってのがあっても、無視してOK。
え?
無視してよいんですか?
個人的には無視できないですけど。
というか、これ無視してよいなら、
田部さんが何を意図 して grep しろといっているのか
わからないです。
それとも、そういうプログラムを発見したら、
それを書いたプログラマを「無視してOK」?
ところで、キーワード的には static で同じですけど、
局所変数に static をつける話とは
まったく異なる話題と思ってよいんですよね?
以上です。
大学の、世界的な権威を持った、偉い先生かも知れませんよ。
--
関@神奈川
Masao Seki <ma-...@gb3.so-net.ne.jp>
私なんか、最初この質問を見たときに思ったのは
「(1)__FILE__使ってデバッグするのはじめてみた」
「(3)ポインタ使えば?」だったりしますが、
田部さんの皆さんへのRESを見て、
「ああ、色々と苦労してるのね~」と感じました。
その感じに関する記述ですので、
事実とは異なるところがあるかもしれませんので、
この物語はフィクションと言うことで(ぉぃ。
Junn Ohta wrote:
> fj.comp.lang.cの記事<a7mmq6$f5r$1...@bgsv5905.tk.mesh.ad.jp>で
> ta...@mug.biglobe.ne.jpさんは書きました。
> > const char buf[] = "abc" ;
> 規格はともかくとして、なぜこのようなコードを使いた
> いのか、私にはよく理解できませんでした。
田部さん自身は使おうとも思わないし、使うつもりも無いのですが、
<a7aeh4$9op$1...@bgsv5906.tk.mesh.ad.jp>での発言のあったように、
> 100人以上の、
> 複数個所の拠点で、
> 数千KLINEのプログラムを
> 合同開発して、
> 必死に取ったマシンタイムで
> このバグが発覚し、
> 同様問題を、
> 至急 AM6:00まで調査せよ
> って時でも、考えませんか?
規模および掛かっている人員の関係上、歩留まりが悪くなるのは
十分考えられることです(ただし、実際の規模がどうかは未確認)。
たしかに太田さんの言うように、
> 「遅いのは許されない」のなら「データの割り付けを知らないプログラマ」
> などを使うわけにはいかないと思うのですが、違うのかな。
これは無茶苦茶正論です。私も、後のほうの回答ではこれを書きました(^^ゞ
次回の発注時とか、ず~っと同じ人に発注し続ける場合は、
その制御も可能でしょうが、最初とか不定期の発注ではこの制御もできません。
(発注条件に「誰々は使うな」とか「誰々希望」と書くこともできるし)
(私だって、関連会社って制約さえなければ、発注したくない人って
沢山いました。)
だからこそ、
当初の質問は
その、「使うな」に該当する人が書いたコードを無理矢理にでも実用域に
持ち込む方法として
(1)「簡単にチェックする方法って無い」
(printfに関しては、gcc -Wformatオプションってのが答え。
ストリングリテラルの連結に関しては未解決)
(2)「無理矢理でも最適化する方法ってない」
(コレは仕様なのでどうにもならない)
(3)「staticで書くchar型の配列の要素数省略する方法ない」
(これはコンパイラの制約により可/不可がありそうなので、
明確な答えは無し。ちなみに、gccでは、元のままコンパイルが通るし
(^^;
配列の要素数書かないだけだったら、ポインタ使っても問題は無いは
ず。
static const宣言もあるから、readonlyの空間でも全く矛盾はない。)
と私は解釈しました。
以上、解説モード終了。
って、やっぱり大きなお世話か?(爆)
なんか、newsgroupはメールの配信が遅い…………
"Masamichi Motoyoshi" <sa...@dsl.gr.jp> wrote in message
news:a7qdjb$7v0$1...@sv.dsl.gr.jp...
> 本吉です。
> C言語に static というキーワードがあることを
> 知らないだけという説もあると思いますけどね。
うう、確かに。
> > あと、
> > static char sccsid[] = "なんとか" ;
> > static char cvsid[] = "こんとか" ;
> > ってのがあっても、無視してOK。
> え?
> 無視してよいんですか?
> 個人的には無視できないですけど。
この、
SCCSとか、
CVSとかはUNIXのソース管理システムで、
お約束で、無視して良い事になってます。
#ident "ソースコード第何版”
が使えれば、良いのだけれどANSI-C標準では無いもので。。。。
> というか、これ無視してよいなら、
> 田部さんが何を意図 して grep しろといっているのか
> わからないです。
上記以外では、
僕の意図と
本吉さんの理解は多分あってます。
> それとも、そういうプログラムを発見したら、
> それを書いたプログラマを「無視してOK」?
そこまで惨い事言わないが、
ヘッダファイルで
static int i = 0 ;
とか、
へっダファイルで
static char Roop ; /* char? R?L? */
とか、だったら言うかもしれない。
> ところで、キーワード的には static で同じですけど、
> 局所変数に static をつける話とは
> まったく異なる話題と思ってよいんですよね?
どの程度、static が理解されていいるかの、
評価方法の一つです。
> > buf[] の初期化は func 呼び出しと一対一関係にないといけない, と規格にあ
> > ります (私も以前片山さんに指摘されました).
初期化だけでなくてオブジェクトのインスタンス生成もそうでした.
6.2.4 Storage durations of objects
...
[#5] For such an object that does not have a variable length
array type, its lifetime extends from entry into the block
with which it is associated until execution of that block
ends in any way. (Entering an enclosed block or calling a
function suspends, but does not end, execution of the
current block.) If the block is entered recursively, a new
instance of the object is created each time. The initial
value of the object is indeterminate. If an initialization
is specified for the object, it is performed each time the
declaration is reached in the execution of the block;
otherwise, the value becomes indeterminate each time the
declaration is reached.
> 上の変態コードも規格上はエラーにならん
かといって動作保証があるわけではありませんね.
6.7.3 Type qualifiers
...
[#5] If an attempt is made to modify an object defined with
a const-qualified type through use of an lvalue with non-
const-qualified type, the behavior is undefined. If an
attempt is made to refer to an object defined with a
volatile-qualified type through use of an lvalue with non-
volatile-qualified type, the behavior is undefined.113)
> ので、const だけだったらstatic に勝手になっちゃうのは、やっぱり余計
> なお世話な気がするです。
ところでこんな記述もあるんですが….
[#3] The properties associated with qualified types are
meaningful only for expressions that are lvalues.112)
____________________
112The implementation may place a const object that is not
volatile in a read-only region of storage. Moreover, the
implementation need not allocate storage for such an
object if its address is never used.
> > > buf[] の初期化は func 呼び出しと一対一関係にないといけない, と規格にあ
> > > ります (私も以前片山さんに指摘されました).
この辺りを先輩に聞いてみたところ, 「それは
extern char first_char (void);
extern char second_char (void);
extern char third_char (void);
void
foo (void)
{
const char buf[] = {
first_char (),
second_char (),
third_char (),
'\0',
};
...
}
のような場合にイニシャライザの各関数が毎回呼ばれることを保証するための
もので, イニシャライザが文字列リテラルのような形で与えられ, かつ, buf
のアドレスが外に流失しない場合, buf を read-only な領域へ置くことは別
に構わないんじゃないか」という意見でした.
| ただ,そんな不毛な最適化をコンパイラがやってくれても,誰もうれしくな
| いハズ。そういう用途なら const char* もしくは static const char[] で
| 十分なんだから。
というのは太田さんの意見に合致しますね.
私としてはじゅうぶん実現可能な意見だったつもりなの
ですが...。
> 次回の発注時とか、ず~っと同じ人に発注し続ける場合は、
> その制御も可能でしょうが、最初とか不定期の発注ではこの制御もできません。
> (発注条件に「誰々は使うな」とか「誰々希望」と書くこともできるし)
> (私だって、関連会社って制約さえなければ、発注したくない人って
> 沢山いました。)
そうなんですか!?
田部さんが挙げられたconstの問題って、設計時にデー
タレイアウトについて基本ルールを作って「必要のない
かぎりスタックにデータを置くな」と決めておけばすむ
話ですよね? で、それが理解できない程度のプログラマ
ーってそんなにいるのかしら...。
いま私のまわりにも100人くらいの開発者がいて、協力
会社メンバー(いわゆる外注さん)もいくつかのところか
ら来てもらっているのですが、「発注したくない」とい
うレベルの人はひとりもいないですよ。
> だからこそ、
> 当初の質問は
> その、「使うな」に該当する人が書いたコードを無理矢理にでも実用域に
> 持ち込む方法として
# 田部さんとこのReview-Cを買って使う。:-)
> (1)「簡単にチェックする方法って無い」
> (printfに関しては、gcc -Wformatオプションってのが答え。
> ストリングリテラルの連結に関しては未解決)
構文レベルの問題なら、テキスト処理プログラムを組み
合わせればさほど苦労せずにチェックできる場合が多い
と思いませんか?
たとえば文字列リテラルの連結があるかどうかをチェッ
クしたいのなら、すべてのソースに対して
(1) プリプロセッサーを通し(cc -E)
(2) 残ったプリプロセッサー指示行を捨て(grep -v)
(3) すべての空白(スペース、タブ、改行)を捨て(tr -d)
(4) 残りのテキスト中に""があるかどうか調べる
でだいたいの目的は果たせそうな気がします。
(3)の結果は改行のない1行の長ーいテキストになるので、
(4)の処理に何を使うかでちょっと悩むかもしれません
が、Cで書いたってちょこちょこっと書けちゃう程度の
ものですよね。
で、上のように処理すると空文字列("")とか
"Can't open \"%s\""
のような文字列まで引っかかってくることになりますが、
その程度のfalse matchならたいして邪魔にならないで
しょう。あるいは(1)の前に、ソース中にロコツに存在
する""(そこにはおそらくバグはないはず)を何か別の文
字列に置き換えてやってもよいですしね。
で、これを「複数箇所の拠点にある」「数千KLINEのプ
ログラム」(プログラム本数にして1000本くらい?)につ
いてチェックするとしても、準備も合わせて1時間もか
からないのではないかと思います。
というわけで、私にはどうも田部さんの危機感があまり
ダイレクトには伝わってこないんですよね...。
"Tadamasa Tamura" <ta...@coral.ocn.ne.jp> wrote in message
news:3CA0CCB1...@coral.ocn.ne.jp...
> 田村です。
> とりあえず、今回は解説モードで。
中略
> 田部さんの皆さんへのRESを見て、
> 「ああ、色々と苦労してるのね~」と感じました。
涙涙、
田村さんはいつも、
私の、稚拙な日本語を正確に理解してくださる。
尚、下記は
> 100人以上の、
> 複数個所の拠点で、
> 数千KLINEのプログラムを
> 合同開発して、
> 必死に取ったマシンタイムで
> このバグが発覚し、
> 同様問題を、
> 至急 AM6:00まで調査せよ
事実に基づくフイクション、って所です。
> なんか、newsgroupはメールの配信が遅い…………
同感。
全然関係無いけれど、
http://groups.google.com/groups?q=fj.comp.lang.c&hl=ja
の、化け字はなんでだろう。
―――――――――――――――――――――――
"Junn Ohta" <oh...@src.ricoh.co.jp> wrote in message
news:a7uhtj$jvq$1...@ns.src.ricoh.co.jp...
> fj.comp.lang.cの記事<3CA0CCB1...@coral.ocn.ne.jp>で
> ta...@coral.ocn.ne.jpさんは書きました。
> > たしかに太田さんの言うように、
> > > 「遅いのは許されない」のなら「データの割り付けを知らないプログラマ」
> > > などを使うわけにはいかないと思うのですが、違うのかな。
> > これは無茶苦茶正論です。私も、後のほうの回答ではこれを書きました(^^ゞ
>
> 私としてはじゅうぶん実現可能な意見だったつもりなの
> ですが...。
太田さん。
grep static *.h
してくれました?
流通に耐える、フリーソフトでなくて。。。。。
>
> 田部さんが挙げられたconstの問題って、設計時にデー
> タレイアウトについて基本ルールを作って「必要のない
> かぎりスタックにデータを置くな」と決めておけばすむ
> 話ですよね? で、それが理解できない程度のプログラマ
> ーってそんなにいるのかしら...。
だから、
grep static *.h
なんか、出たか、出なかったか
興味津々。
> いま私のまわりにも100人くらいの開発者がいて、協力
> 会社メンバー(いわゆる外注さん)もいくつかのところか
> ら来てもらっているのですが、「発注したくない」とい
> うレベルの人はひとりもいないですよ。
grep static *.hで、
なんか出たか時の対応は、
「世界的な権威を持った、偉い先生」の
tom...@nibb.ac.jp さんと、
本吉さんへの、
レスで回答済み。
>
> > だからこそ、
> > 当初の質問は
> > その、「使うな」に該当する人が書いたコードを無理矢理にでも実用域に
> > 持ち込む方法として
>
> # 田部さんとこのReview-Cを買って使う。:-)
fjでは、営業禁止なので、
「王様の耳はロバの耳」って言いたかった
って書いておこう。
だって、凄く、「XXX」が「YYY」なんだもん。
>
> > (1)「簡単にチェックする方法って無い」
> > (printfに関しては、gcc -Wformatオプションってのが答え。
> > ストリングリテラルの連結に関しては未解決)
>
> 構文レベルの問題なら、テキスト処理プログラムを組み
> 合わせればさほど苦労せずにチェックできる場合が多い
> と思いませんか?
これは、"Takashi SAKAMOTO" へ発注済みです。
http://groups.google.com/groups?hl=ja&th=f27fc10aae2b44d6
早く、見ないと消えちゃう。
> というわけで、私にはどうも田部さんの危機感があまり
> ダイレクトには伝わってこないんですよね...。
太田さん
http://rec.ncos.co.jp
で、約10分も、ご遊覧くださったのに、まだ駄目?
このスレッド深くなりすぎたので、
新しいスレッドを立てますね。
予告:
・日本人「は|も」static を知らない
・日本人のBYTEへの異常な愛情
> --
> 太田純(Junn Ohta) (株)リコー/新横浜事業所
> oh...@sdg.mdd.ricoh.co.jp
―――――――――――――――――――――――――――
やってみました。うちで開発していて私がすぐアクセス
できる範囲のソースコード(行数数えてないけど10万行
程度かな)には「これってだめじゃん」なstaticは見つ
かりませんでした。なお、このソースコードのかなりの
部分は私以外の人間が書いたものです。
それ以前に、これまで20年にわたって行ってきたソース
コードレビュー(100万行単位になるはず)でも、そうい
ったstaticの誤用を見た記憶がないんですね。というわ
けで、私の印象ではこの手の誤用はC言語入門教育の段
階で早々にスクリーニングして排除できるとしか思えな
いわけですよ。
こうまで田部さんと私とで印象が違うとしたら、世間一
般が標準と考えているプログラミングスキルというのが
どのへんのレベルにあるのか非常に気になります。よそ
はどうなんだろう...。
> > というわけで、私にはどうも田部さんの危機感があまり
> > ダイレクトには伝わってこないんですよね...。
> 太田さん
> http://rec.ncos.co.jp
> で、約10分も、ご遊覧くださったのに、まだ駄目?
駄目でした。
Junn Ohta wrote:
> > grep static *.h
> > してくれました?
> (中略)
> 「これってだめじゃん」なstaticは見つかりませんでした。
> なお、このソースコードのかなりの
> 部分は私以外の人間が書いたものです。
な、なんか悔しい(^^;
> staticの誤用を見た記憶がないんですね。
さ、さらに悔しい...
> 私の印象ではこの手の誤用はC言語入門教育の段
> 階で早々にスクリーニングして排除できるとしか思えな
> いわけですよ。
「staticに領域を確保する」ってことは覚えてても、
可視範囲がプライベートになるってことは覚えてないみたいですね(^^;
(static宣言しない関数はDynamic loadするとでも思ってるんだろうか?(笑))
> よそはどうなんだろう...。
私も事実に基づくフィクションってことで。
もう10年位前のことですが
Scene1:謎のlibm
とあるプログラムをリンクしていたとき、ある日突然
Undefined symbol : (関数名失念。浮動小数点演算関数)
と出た。
追いかけてみると、とあるところでその関数を発見。
(注:そのモジュールが扱うテーブル数は多くて256個(笑))
その担当に聞いてみると、ハッシュテーブルを参照する際に
使っているらしい。
で、もともとど~頑張っても256個程度しか扱わないのに、
(しかも、配置座標という別種のインデックス付きデータで)
何でハッシュテーブルを使用しているのかを聞いてみると、一言。
「使ってみたかったから」
趣味で作ってんじゃね~(爆)
Scene2:これって緑?
その、とあるプログラム関連で、グラフィックライブラリ経由で緑色を
指定すると、どこをどう見ても綺麗な緑色に見えない。
ソースコードをかっぱらって(ぉぃ、追いかけてみると
緑色のカラーマップが
R:(確か100以上の値) G:255 B:(確か100以上の値)
で、その担当に聞いてみると、一言。
「本にそう載ってたから」
100歩譲って「直さん?」と言ったら、
「本がそうなってるから」………………(--#
他にも色々あるけど、このへんで(笑)
> > http://rec.ncos.co.jp
> > で、約10分も、ご遊覧くださったのに、まだ駄目?
> 駄目でした。
私が見て直感的に感じたこと。
「これ、\98,000-で売れるの?(笑)」だったりして(^^ゞ
というのも信じがたいのです。1人や2人そういう人間が
いたかもしれませんが、もっと一般的に「そういう傾向
がある」とくくれるほどの人数には出会ったことがない
もので...。
> 私も事実に基づくフィクションってことで。
> もう10年位前のことですが
>
> Scene1:謎のlibm
これ、スキルの問題ではなくて開発に対する姿勢の問題
ですよね。田部さんの頭を悩ましているようなスキルの
問題については逆にクリアされているといってもよさそ
うな気がします。
でもなんでそんなコードを書くんだろう。どういう品質
のものを開発するかについては設計時に明らかにされて
いるわけですから、それに反するようなコードを書こう
と思ったりしないのがふつうですよね。それとも設計と
開発がまったく分離していて、開発部署には機能仕様ぐ
らいしか渡ってこないのかな? 品質向上の指標とかデー
タレイアウトみたいなものが存在しない?
> Scene2:これって緑?
そんなもん、その本を捨てさせて終わりでしょう。:-)
どういう参考文献を利用したらよいかについては教育の
一部ですね。これも開発開始時に設計側からある程度の
情報提供を行えばすむ話です。
というわけで、なんか設計・開発部隊の作りかたそのも
のに問題があるような気がしません?
> 私が見て直感的に感じたこと。
> 「これ、\98,000-で売れるの?(笑)」だったりして(^^ゞ
これだけ具体的な機能をもつソフトなら、うまく使えば
すぐに元がとれそうです。10人が1日かかってデバッグ
するよりずっと安くつくわけですから。
それよりも、こういうソフトがありがたいほど役に立つ
現場ってどんな現場なんだ、というほうが私にとっては
よっぽど脅威なんですが...。
私は、【重要・注意事項】に「このプログラムの一部は、データの割り付けを
知らないプログラマが見様見真似で書いています」と書いておいてほしいと思
いました。
それを読んでどのように判断するかは客次第。
--
N-Yas <cep0...@nyc.odn.ne.jp>
"tabe" <ta...@mug.biglobe.ne.jp> writes:
> これは、"Takashi SAKAMOTO" へ発注済みです。
> http://groups.google.com/groups?hl=ja&th=f27fc10aae2b44d6
> 早く、見ないと消えちゃう。
なんですが、必要なのはピンポイントのチェック機能で、別に構文まで見なく
ても実用には耐えそうな気がするのですが。
oh...@src.ricoh.co.jp (Junn Ohta) writes:
> たとえば文字列リテラルの連結があるかどうかをチェッ
> クしたいのなら、すべてのソースに対して
> (1) プリプロセッサーを通し(cc -E)
> (2) 残ったプリプロセッサー指示行を捨て(grep -v)
> (3) すべての空白(スペース、タブ、改行)を捨て(tr -d)
> (4) 残りのテキスト中に""があるかどうか調べる
> でだいたいの目的は果たせそうな気がします。
>
> (3)の結果は改行のない1行の長ーいテキストになるので、
> (4)の処理に何を使うかでちょっと悩むかもしれません
> が、Cで書いたってちょこちょこっと書けちゃう程度の
> ものですよね。
Junn Ohta さんの提案されているような方法で、十分作業の負荷は軽減できる
と思うのですが、全てのケースに対応できるような「製品」がないと駄目なん
でしょうか?
# 何でもかんでも C Compiler の中で閉じないと駄目なのですか?
my printf の場合でも、プリプロセッサを通して、指示行を捨てて…テキスト
中から my printf の部分を抜き出して、文字列部分の % の数と引数の数を比
較する程度で。
私も Ohta さんのおっしゃられるように
> > というわけで、私にはどうも田部さんの危機感があまり
> > ダイレクトには伝わってこないんですよね...。
と危機感が伝わりません。それだけ問題視しているのに、「perl で簡単な
check script を用意する」とかそういう手段を用意されてない(ように感じる)
アンバランスさがそう思わせているのかもしれません。
--
---
Takashi SAKAMOTO (PXG0...@nifty.ne.jp)
"red brick" <f...@qc4.so-net.ne.jp> wrote in message
news:2HBn8.5$qI2....@newsall.dti.ne.jp...
> 御意。しかしながら、それでもバグは出るものなのです。
そうですね、出ます。
バグの博覧会は、http://rec.ncos.co.jp
遊んでって下さい。
> # バグじゃない不具合ってのもあるし。
・しょうのないBUG
・仕様のないBUG(#これが一番つらいかな)
・使用のないBUG(#でも、売れなければご飯食べれないし)
#あんまり面白くないか。
"Junn Ohta" <oh...@src.ricoh.co.jp> wrote in message
news:a80jsm$9hn$1...@ns.src.ricoh.co.jp...
> > 私が見て直感的に感じたこと。
> > 「これ、\98,000-で売れるの?(笑)」だったりして(^^ゞ
売れません。(^^ゞ
「勝手使って 」を別の漢字で書きたい!!。
> これだけ具体的な機能をもつソフトなら、うまく使えば
> すぐに元がとれそうです。10人が1日かかってデバッグ
> するよりずっと安くつくわけですから。
BUG1件って幾らなんでしょうね?
公開してる会社はないでしょうけど。
> それよりも、こういうソフトがありがたいほど役に立つ
> 現場ってどんな現場なんだ、というほうが私にとっては
> よっぽど脅威なんですが...。
長老太田様、
この一言で、昨日は450アクセスの
新記録でした。
ありがとうございます。
って事は、
「ありがたいほど役に立つ現場って」。。。。。
バグひとつ潰していくら、という商売でもあれば楽しい
んですけどね(※)。上の試算は残念ながらただの時間給
換算です。
※ゲーム業界ではテスト専門の会社があってバグを発見
すればするほど喜ばれる(そこに頼んだ甲斐がある)よ
うですが、それでもバグひとついくら、という計算で
はないみたいですね。
> 長老太田様、
長老扱いはやめてください。ここには商用コンパイラー
作ってン十年、みたいな方まで出入りしているんですか
らね。私なんぞただのヒヨッコ。
In article <3CA3603A...@coral.ocn.ne.jp>,
Tadamasa Tamura <ta...@coral.ocn.ne.jp> writes
>> 「これってだめじゃん」なstaticは見つかりませんでした。
>> なお、このソースコードのかなりの
>> 部分は私以外の人間が書いたものです。
>な、なんか悔しい(^^;
僕も自分で書くときはやらないけど、学生が手直しした部分には
入っているのを見てしまいました。
>「staticに領域を確保する」ってことは覚えてても、
>可視範囲がプライベートになるってことは覚えてないみたいですね(^^;
名前があってないからなぁ...
---
Shinji KONO @ Information Engineering, University of the Ryukyus,
PRESTO, Japan Science and Technology Corporation
河野真治 @ 琉球大学工学部情報工学科,
科学技術振興事業団さきがけ研究21(機能と構成)