システムヘッダでBYTEを提供している開発環境ならともかく、
プロジェクトリーダーがわざわざ、
BYTEをtypedef して、
開発担当者を、地獄に突き落としてる例がこれです。
で、またまた
「fj.comp.lang.c」の皆様に質問、
質問1:
「
現代の32BIT以上のCPUにおいて、
なぜ、素直に int 型や、char *を使用しないで
BYTEなんか導入する
プロジェクトが存在するんだろう?
」
質問2:
「
なぜ、整数型 int を記述すべきところで
char LoopCnt ;
char i ;
と、char を使用する人が後を絶たないのだろう
」
補足:
構造体の中や、
I/Oを伴う物では
unsigned char が必要である事は承知してます。
以上よろしくお願いします。
――――以下:BYTEへの異常な愛情――――――
#include <stdio.h>
#include <string.h>
/*******************************/
typedef unsigned char BYTE ;
/*******************************/
static BYTE *mes[] = {
(BYTE *)"BYTEが、",
(BYTE *)"好きなら、",
(BYTE *)"ゲロを吐く"
} ;
static BYTE byte(BYTE id)
{
BYTE i ;
BYTE buf[BUFSIZ] ;
switch((int)id) {
case 0:
for(i = 0 ; i < 0x100 ; i += 3) {
(void)strcpy((char *)buf,(char *)mes[i%3 + 0]) ;
(void)strcat((char *)buf,(char *)mes[i%3 + 1]) ;
(void)strcat((char *)buf,(char *)mes[i%3 + 2]) ;
(void)printf("%s\n",(char *)buf) ;
}
return 0 ;
case 1000:
return (BYTE)-1 ;
}
return (BYTE)-1 ;
}
int main(void)
{
int i ;
for(i = 0 ; i <= 1000 ; i += 1000) {
BYTE ret = byte(i) ;
if(ret == (BYTE)-1) {
(void)printf("%d\n",ret) ;
}
}
return 0 ;
}
――――――――――――――――――
以上
見て、勝手使って http://rec.ncos.co.jp
> 日本人って小さい物が好きですね。
格上げを知らないだけでは?
あるいは、他言語出身の人など
Cのそういう所が精神的に受け容れられない人が
結構いますよね。
> システムヘッダでBYTEを提供している開発環境ならともかく、
> プロジェクトリーダーがわざわざ、
> BYTEをtypedef して、
> 開発担当者を、地獄に突き落としてる例がこれです。
unsigned char というスペルが無駄に長ったらしい
と感じることなら私もあります。
> 現代の32BIT以上のCPUにおいて、
> なぜ、素直に int 型や、char *を使用しないで
> BYTEなんか導入する
> プロジェクトが存在するんだろう?
機械寄りのコードを書いているときなど、
文字でないものに char と書くのが気持ち悪い
と感じることなら私もあります。
# void* が ++ できたら気が楽だったと思う
> なぜ、整数型 int を記述すべきところで
> char LoopCnt ;
> char i ;
> と、char を使用する人が後を絶たないのだろう
他方で「int こそ、気安く使うべきではない」と言う人もいますよね。
たとえば、typedef int int32; のようなことです。
総じて。
typedef unsigned char BYTE; くらいなら容認してもよいのでは?
--
山口@福岡 <hy...@mx7.tiki.ne.jp>
"Yoshiki Kataoka" <kat...@ka2.so-net.ne.jp> wrote in message
news:a83p16$e1i$1...@news01ci.so-net.ne.jp...
> 田部さん、こんにちは。 片岡と申します。
はい、今晩は。
> > 日本人って小さい物が好きですね。
> 格上げを知らないだけでは?
unisgned char uc = 0xFF ;
signed char c = 0xFF ;
printf("%x\n",uc) ;
printf("%x\n",c) ;
の出力を正確に言えて、
かつ差分の理由を正確に言える人、結構少ない。
後、私も実は2年前まで知らなかったが
「ピュアchar」 の事を知っている人は、
ほとんどいないのでは?
> あるいは、他言語出身の人など
> Cのそういう所が精神的に受け容れられない人が
> 結構いますよね。
charに整数を入れてもOK!ってな
なんでもありの精神の事ですか?
> > 開発担当者を、地獄に突き落としてる例がこれです。
> unsigned char というスペルが無駄に長ったらしい
> と感じることなら私もあります。
究極は、これ
typedef unsigned char UB ;
typedef signed char SB ;
typedef unsigned short UH ;
typdef signed short SH ;
この人達のレビュー風景を想像すると、ちょと楽しい。
。。。。「うび」?。。。。
「うび」!!
。。。。。だって、「すび」だと。。。
「うは」?
だから 、「うは」だと。。。。
「すは」でなければ。
うび、うは、うび、うは(合唱)
私も、 #include <types.h>で
uchar って書きますけれどね。
> > BYTEなんか導入する
> > プロジェクトが存在するんだろう?
>
> 機械寄りのコードを書いているときなど、
> 文字でないものに char と書くのが気持ち悪い
> と感じることなら私もあります。
> # void* が ++ できたら気が楽だったと思う
そうですね。。。
(void)*((volatile unsigned char *)0x80000) ;
ってな時,キャラクターのchar は気持ちとしては解ります。
> > なぜ、整数型 int を記述すべきところで
> > char LoopCnt ;
> > char i ;
> > と、char を使用する人が後を絶たないのだろう
>
> 他方で「int こそ、気安く使うべきではない」と言う人もいますよね。
> たとえば、typedef int int32; のようなことです。
C-FAQ 1.3ですね。
#あれ、WEBでは欠番みたい。
私の経験則で申しわけないでが、
関数の返却値に、
char
unsigned char
short
unsignd short
int
を、選り取りみどりに使用するプロジェクトは
総じて品質が低いです。
#符号拡張や、その他をキャストで誤魔化しまくるはめになるため。
関数の返却値は
・int
・void
・struct tag *
の3点セットのどれかで、
責めまくるプロジェクトは事故が少ない。
> 総じて。
> typedef unsigned char BYTE; くらいなら容認してもよいのでは?
というわけで、
もう少し皆さんの意見を聞いてみましょう。
――――――――――――――――――――――――――
"H.Yamaguchi" <hy...@mx7.tiki.ne.jp> wrote in message
news:a83odi$9jf$1...@nntp-kyusyu.tiki.ne.jp...
>
> こんどは、混沌の館ですか。(^^
山口@福岡さん今晩は。
混沌の館って初め、
藤原さんの、「藤原博文の館」の事かと思った。
今は、「パソコン初心者の館」って名前みたい
http://www.pro.or.jp/~fuji/mybooks/yakata.html
次に、日経バイトの連載でもあったなー
あれ?、これBYTEにかけてる?
そんで、ドンピシャ
「混沌の館」ってHPもありますね。
http://www1.odn.ne.jp/~cbi12830/sub3.htm
これは、笑える。
では、では。
――――――――――――――――――――――――
今回はちょっとだけ田部さんいぢめも~ど。
tabe wrote:
> システムヘッダでBYTEを提供している開発環境ならともかく、
> プロジェクトリーダーがわざわざ、
> BYTEをtypedef して、
> 開発担当者を、地獄に突き落としてる例がこれです。
>
> 質問1:あ~んど質問2:
え~っと、プロジェクトリーダさんが、組み込み系出身とか?
で、8~16bit系プロセッサと32bit以上のプロセッサの、データの取り扱いに
関するコンセプトが全然違うってのを知らないとか?
ちなみに、
> 「int 型や、char *を使用しないで
> BYTEなんか導入するプロジェクトが存在するんだろう? 」
とすると、田部さんの周りにも沢山あるでしょ?<成果物
「マイコン搭載~」とか「マイコン内蔵~」とか(笑)
その世界では、
ROM:数キロバイト~数十キロバイト、
RAM:数キロバイト~十数キロバイト
の世界が一般的ですから、1バイトのRAMを削るのは、
ある意味至上命題です。
更に、8bit用のコンパイラも、きっとintは16bitなので、
結果的にBYTEを導入せざるおえない状況になっているはず。
(しかも、コンパイラがpoorな可能性も否定できない)
ここで問題なのは、そのプロジェクトリーダーさんが、
以下のどの問題を抱えているかということかと。
(1)作っているプログラムの対象としている
プラットフォームを理解していない
(2)プラットフォーム毎に異なるアーキテクチャに対し、
ソースコードの改変の必要性が理解できていない
(メモリ容量優先なのか、速度優先なのか等)
(まあ、Cの良さでもあり、悪さでもある<intのサイズが未定義)
(3)その他
で、OJTで「1バイトも無駄にすんじゃね~」と教えれられていると、
そ~ゆ~コードがゲロゲロ出てくるんじゃないかな?(笑)
とりあえず、プロジェクトりぃだぁさんの再教育をお勧めしておきます。
ちなみに、
> typedef unsigned char BYTE ;
> (中略)
> static BYTE byte(BYTE id)
> {
> BYTE i ;
> BYTE buf[BUFSIZ] ;
> (更に略)
> switch((int)id) {
> case 0:
↓無限ループしません?
> for(i = 0 ; i < 0x100 ; i += 3) {
↓i%3って意味無し?
> (void)strcpy((char *)buf,(char *)mes[i%3 + 0]) ;
> case 1000:←来ない?
↓unsignedのリターン値に'-'を付ける感性が…(^^;
> return (BYTE)-1 ;
"Tadamasa Tamura" <ta...@coral.ocn.ne.jp> wrote in message
news:3CA639F2...@coral.ocn.ne.jp...
> 今回はちょっとだけ田部さんいぢめも~ど。
いつも、稚拙な田部語の翻訳ありがとうございます。
以下長文失礼します。
> tabe wrote:
> > BYTEをtypedef して、
> > 開発担当者を、地獄に突き落としてる例がこれです。
> >
> > 質問1:あ~んど質問2:
> え~っと、プロジェクトリーダさんが、組み込み系出身とか?
> で、8~16bit系プロセッサと32bit以上のプロセッサの、データの取り扱いに
> 関するコンセプトが全然違うってのを知らないとか?
typedef unsigned char BYTE ;
の定義を行う人は、
マイクロソフト社の開発環境に慣れた人が、
UNIX環境や、
組込みクロス環境に持ち込む場合が多い様です。
悲劇は、32BIT-CPU環境であるにも、かかわらずず、
typedef unsigned short WORD ;
と定義され、
これが基本的な型として使用された場合にも発生します。
この場合のWORDは
shortから、int(32BIT)への拡張命令をコンパイラが発生するため、
処理速度が無意味に遅くなります。
> > 「int 型や、char *を使用しないで
> > BYTEなんか導入するプロジェクトが存在するんだろう? 」
> とすると、田部さんの周りにも沢山あるでしょ?<成果物
> 「マイコン搭載~」とか「マイコン内蔵~」とか(笑)
組込み系に限りません。
32BIT-CPU を使用するプロジェクト共通ヘッダで、
typedef unsigned short WORD ;
typedef unsigned long DWORD ;
と定義され、int 使用禁止と
「コーディング規約」で定義された場合、
私の知っている限りのコンパイラでは
int == long
int != short であるにも関わらず、
日本人の多くは、
WORDを基本型として選択します。
#DWORDは打ち込み量が多く、
#なんとなく贅沢な印象を日本人に与えるためと私は考えています。
このため、short から int (==long)への拡張命令が発生して
処理速度を遅くします。
> その世界では、
> ROM:数キロバイト~数十キロバイト、
> RAM:数キロバイト~十数キロバイト
> の世界が一般的ですから、1バイトのRAMを削るのは、
> ある意味至上命題です。
組込み系に特化した、ある種のコンパイラは
char->short->int 32bitへの拡張命令を生成しないそうです。
ですが、
組込み系でも、ANSI-C準拠を売ったコンパイラでは
拡張命令が発生しています。
で、
ROM:
BYTEを使用した場合、意図に反して
32bitへの拡張命令が生成されるため、
int を使用した場合より、サイズが大きくなるはずです。
RAM:
int を使用した場合、
現代のコンパイラは、auto ではなく,
register に巧く割り付けるので、
スタックの消費を気にする事はないのではないかと
私は考えています。
#ただし、構造体や配列は register に割り付けられないので別。
ここら辺の実際の所は組込み系の方の
意見も聞いてみたいです。
> 更に、8bit用のコンパイラも、きっとintは16bitなので、
> 結果的にBYTEを導入せざるおえない状況になっているはず。
> (しかも、コンパイラがpoorな可能性も否定できない)
8BIT、16BITの場合は、
田村さんの考えの通りだと思います。
> ここで問題なのは、そのプロジェクトリーダーさんが、
> 以下のどの問題を抱えているかということかと。
>
> (1)作っているプログラムの対象としている
> プラットフォームを理解していない
> (2)プラットフォーム毎に異なるアーキテクチャに対し、
> ソースコードの改変の必要性が理解できていない
> (メモリ容量優先なのか、速度優先なのか等)
> (まあ、Cの良さでもあり、悪さでもある<intのサイズが未定義)
> (3)その他
その他、と私は考えています。
昔から、
typdef unsigned char BYTE ;
typeef unsigned short WORD ;
と、書いていたから、今回のプロジェクトでも同じ。
(そう、MD-DOSの時代から)
> で、OJTで「1バイトも無駄にすんじゃね~」と教えれられていると、
> そ~ゆ~コードがゲロゲロ出てくるんじゃないかな?(笑)
> とりあえず、プロジェクトりぃだぁさんの再教育をお勧めしておきます。
難儀だな。。。(笑い)
ハンガリー記法とのBYTEと、
日本人気質が妙にマッチしてしまうから
いらん苦労をせねばならん。
みんな、
BYTE,WORD,char,shortを使うのやめて、
int を使って早く家に帰ろう。
> > BYTE i ;
中略(全文はこちら)
http://news.dinf.ne.jp/news/fj/comp/lang/c/msg00200.html
> ↓無限ループしません?
> > for(i = 0 ; i < 0x100 ; i += 3) {
しないでーーす。
その前にゲロ吐いて、死にます。
―――――――――――――――――――――――――
> unisgned char uc = 0xFF ;
> signed char c = 0xFF ;
> printf("%x\n",uc) ;
> printf("%x\n",c) ;
> の出力を正確に言えて、
> かつ差分の理由を正確に言える人、結構少ない。
うわ、マジっすか?
だとすると、
> 開発担当者を、地獄に突き落としてる
本当の原因は社員スキル管理の失策じゃないのかな。
上記サンプルの差分がたまたま皆無となる場合の理由まで
正確に言えるようでないとCって危なくて使えないと思います。
例えば、未定義と処理系定義を一緒にしてる人とか
田部さんのまわりには、そんなにはびこっているんですか?
> charに整数を入れてもOK!ってな
> なんでもありの精神の事ですか?
いや、レジスタ・サイズやバス幅の関係とかです。
# char は名前が変なだけ
> うび、うは、うび、うは(合唱)
ちゃんと合唱できてれば問題ないと思います。
不協和音になる場合が問題なのであって。
> 私も、 #include <types.h>で
> uchar って書きますけれどね。
んだ、んだ。
> 私の経験則で申しわけないでが、
> 関数の返却値に、
> char
> unsigned char
> short
> unsignd short
> int
> を、選り取りみどりに使用するプロジェクトは
> 総じて品質が低いです。
> #符号拡張や、その他をキャストで誤魔化しまくるはめになるため。
キャストって誤魔化しなんですか?
私は、暗黙キャストに任せっきりで
その法則に関心がない人こそ怖いのだと思います。
main()
{
auto c;
float f;
scanf("%d", &c);
f = ctof(c);
}
float ctof(c)
{
return c * 9 / 5 + 32;
}
# そういえば www.ioccc.org のトップページが少し変わりましたね
> もう少し皆さんの意見を聞いてみましょう。
賛成
This message is reply to tabe - san
(Subject was : Re: 日本人のBYTEへの異常な愛情)
Message-ID: <a86v3t$l4$1...@bgsv5905.tk.mesh.ad.jp>
in Sun, 31 Mar 2002 21:16:30 +0900 ...
> > その世界では、
> > ROM:数キロバイト~数十キロバイト、
> > RAM:数キロバイト~十数キロバイト
> > の世界が一般的ですから、1バイトのRAMを削るのは、
> > ある意味至上命題です。
>
> 組込み系に特化した、ある種のコンパイラは
> char->short->int 32bitへの拡張命令を生成しないそうです。
> ですが、
> 組込み系でも、ANSI-C準拠を売ったコンパイラでは
> 拡張命令が発生しています。
これは、必ずしも int への拡張を実際に行う必要はないそうです。
「int への拡張を行った場合と同じ」結果であれば。
たとえば、組み込み系ではないにもかかわらず、C++ Builder のコンパイ
ラは、signed char 同士、unsigned char 同士の比較の際には、汎整数拡張
を行いません。singed char と unsigned char の比較では、それぞれ、
signed int と unsigned int に実際に拡張したあとで、比較します。
いずれにしても、char 同士だから int 同士よりも速いとはいえませんが。
組み込みに特化したコンパイラでは、signed char と unsigned char で
も、符号拡張せずに比較する場合が確かにあります。
このため、
singed char sc = 0xff;
unsigned char uc = 0xff;
だと、 sc == uc が成立してしまったりします。
※なので、ANSI に合致してない
実際には、singed と unsigned の混用のほうが問題ですね。
非力なマイコンは、符号付データを直接扱えないので、どうしても、
「符号なしのほうが速い」と思ってしまいます(それは事実)
で、何も考えずに、unsigned で宣言してしまい、それを、符号付の
データと比較すると、時々大小関係が逆になると。
> ROM:
> BYTEを使用した場合、意図に反して
> 32bitへの拡張命令が生成されるため、
> int を使用した場合より、サイズが大きくなるはずです。
というわけで、8bit や 16bit のマイコンだと、char のほうがコードサ
イズも小さくなることが多いですね。
> RAM:
> int を使用した場合、
> 現代のコンパイラは、auto ではなく,
> register に巧く割り付けるので、
> スタックの消費を気にする事はないのではないかと
> 私は考えています。
> #ただし、構造体や配列は register に割り付けられないので別。
こちらは、純粋に、変数が使う領域の問題ですね。
特に、8bit マイコンだとどうあがいてもアライメントの問題が発生しない
(というか、アライメントはBYTE)ので、char の方が領域を食いません。
最近は、比較的 RAM 容量が多くなってきたので、そろそろ、int がデフォ
ルトになってきてはいますね、私の場合でも。
このような事情で、私の場合、組み込みのソフトの浮動小数点は未だに、float
を使っています。
これも、どちらかと言うと、double がデフォルトですよね、一般的には。
特に、「単純な小数点つきの数値リテラル」は、double なので、
float x = 0.1;
if ( x == 0.1) ....
なんてやると、思い切り悩むことになります。
--
* address na...@sep.email.ne.jp is also availableness now.
_/ -- Last 1927 hours until 2002 World Cup final ---------------------
_/ FUJIHARA Keiichi
_/ E-Mail : kei...@fujihara.name <or> na...@qua.net
_/ URL : http://www.keiichi.fujihara.name/
--------------------------------------------+----- Luna Phase 18.64 ---
PGP FingerPrint = 7CC3 4F95 8CC7 87D3 7178 C348 CD65 7F08 D68F 69F6
ファイルやデバイスとのインターフェースが目的ではな
いBYTEの話ですよね?
なんでそんな設計をする人間をプロジェクトリーダーに
したりするんだろう。そういう会社はおそらく、会社ぐ
るみでプログラミングに関するリテラシーが決定的に不
足しているのでしょうね。
# でもそんなプロジェクト、一般論として考慮しなけれ
# ばならないほどたくさんあったりするのか? これも私
# にはちょっと信じがたい話。
> 質問2:
> なぜ、整数型 int を記述すべきところで
> char LoopCnt ;
> char i ;
> と、char を使用する人が後を絶たないのだろう
会社内部で拡大再生産しているようなよっぽど間抜けな
ところでないかぎり、そんな人はすでに絶滅しているの
ではないかと思います。:-)
--
太田純(Junn Ohta) (株)リコー/新横浜事業所
oh...@sdg.mdd.ricoh.co.jp
tabeさんの<a84gkp$hif$2...@bgsv5905.tk.mesh.ad.jp>から
>田部です。
こんにちは。
> unisgned char uc = 0xFF ;
> signed char c = 0xFF ;
> printf("%x\n",uc) ;
> printf("%x\n",c) ;
> の出力を正確に言えて、
> かつ差分の理由を正確に言える人、結構少ない。
言えません。(;^_^A アセアセ…
向学のため、教えて頂きたいのですが、とりあえず、コンパイル、
実行してみたら、
ff
ffffffff
となりました。
unsignedは符号なし、signedは符号あり、という認識しかないので
どうしてこうなるのかが分かりません。
> 「ピュアchar」 の事を知っている人は、
> ほとんどいないのでは?
こちらも知りません。勉強不足ですね。上のこととの
つながりが有るかと思いますが、併せてよろしくお願い致します。
--
hidenori mailto:miyo...@d1.dion.ne.jp
そこまでわかってるなら簡単
unsigned char の 0xFF は 255
signed char の 0xFFは -1
で処理されてるからです。
In article <a89epg$8qo$1...@news.kyosai.or.jp>,
簡単ですか?じゃあ 255 と -1 との違いは?
(signed char)0xff と (unsigned char)0xff との扱いの違いな
んて実装依存なんで、処理系によっては全く同じ結果が得られるこ
とだってあり得ます。
多分そういう処理系は ANSI C は満たさないでしょうけど。
# portability 重視か performance 重視か等、開発 policy に
#よって最適解は異なるので、どういう style が正しいとか間違
#っているとかなんて一概に言い切れることは意外と少ないですよ。
--
しらい たかし
> tabeさんの<a84gkp$hif$2...@bgsv5905.tk.mesh.ad.jp>から
> > unisgned char uc = 0xFF ;
> > signed char c = 0xFF ;
> > printf("%x\n",uc) ;
> > printf("%x\n",c) ;
> > の出力を正確に言えて、
> > かつ差分の理由を正確に言える人、結構少ない。
>
> 言えません。(;^_^A アセアセ…
> 向学のため、教えて頂きたいのですが、とりあえず、コンパイル、
> 実行してみたら、
> ff
> ffffffff
> となりました。
うん。32BIT-CPUでは大抵そうなるね。
> unsignedは符号なし、signedは符号あり、という認識しかないので
> どうしてこうなるのかが分かりません。
char は ■
int は □□□■
一個の■が8BIT
ANSI-C準拠のコンパイラは、char や short を一度 int に拡張する。
■の所を拡大してビットパターンで表すと、
▲△△△△△△△
で、
▲の所をサインビットと言う(符号ビット)
で、
sigined の場合 ▲が立っていると(つまり1だと)
char ■
int ■■■■
となりオールビットONになる(,0xFF、FF、FF、FF)
で、
unsigned の場合 ▲が立っていても
(つまり1でも、符号BITとならないので)
char ■
int □□□■
となり、頭を□(ゼロ)で埋める(0x00、00、00、FF)
あー紙と鉛筆が欲しい(斜め罫線が引きたい)。
説明づまり。
じゃ、練習問題
unisgned char uc = 0x80 ;
signed char c = 0x80 ;
printf("%x\n",uc) ;
printf("%x\n",c) ;
の出力と理由を述べよ。
> > 「ピュアchar」 の事を知っている人は、
> > ほとんどいないのでは?
>
> こちらも知りません。勉強不足ですね。上のこととの
> つながりが有るかと思いますが、併せてよろしくお願い致します。
うん。
int って書くと、
signed int の事を意味する。
でも、
char って書いても
signed char の事を意味しない。
つまり
char 型には
signed char (符号有りCHAR)
unsigned char (符号無しCHAR)
char (ピュアCHAR=まさに文字を表すためのCHAR)
の3種類がある。
で、「うましか」なグループリーダが
typedef unsigned char UB ;
typedef signed char SB ;
のみ許可して、
ピュアCHARを禁止すると、
開発担当者は、
コンパイラが文句言うので
(言わないコンパイラもある、
もしくは、#include <string.h>を記述する習慣が無い)
strcmp((char *)USstr,(char *)SBstr)、
ってな、。
キャスト地獄に行かなくてはいけない。
hidenori mailto:miyo...@d1.dion.ne.jpさん。
これで解った?
"Takashi SHIRAI" <shi...@nintendo.co.jp> wrote in message
news:a89knu$6a3$1...@nsvn01.zaq.ne.jp...
> しらいです。
>
> In article <a89epg$8qo$1...@news.kyosai.or.jp>,
> Sugihara Yoshimi <sugi...@kyosai.or.jp> wrote:
> >> unsignedは符号なし、signedは符号あり、という認識しかないので
> >> どうしてこうなるのかが分かりません。
> >
> >そこまでわかってるなら簡単
> >unsigned char の 0xFF は 255
> >signed char の 0xFFは -1
> >で処理されてるからです。
>
> 簡単ですか?じゃあ 255 と -1 との違いは?
うん。
符号拡張は,結構面倒くさい。
32BIT-CPUにおいて、
以下の出力と理由を述べよ
printf("%x\n",(short)0xFFFF) ;
This message is reply to Sugihara Yoshimi - san
(Subject was : Re: 日本人のBYTEへの異常な愛情)
Message-ID: <a89epg$8qo$1...@news.kyosai.or.jp>
in Mon, 01 Apr 2002 19:48:41 +0900 ...
要素としてはもうひとつ、「Cでは、関数の引数になった char は暗黙のう
ちに int に拡張されるから」というのもありますね。
char (多くは 8bit 幅)のままなら、いずれも、0xff ですから。
--
* address na...@sep.email.ne.jp is also availableness yet.
_/ -- Last 1916 hours until 2002 World Cup final ---------------------
_/ FUJIHARA Keiichi
_/ E-Mail : kei...@fujihara.name <or> na...@qua.net
_/ URL : http://www.keiichi.fujihara.name/
--------------------------------------------+----- Luna Phase 19.15 ---
On 1 Apr 2002 04:43:52 GMT, in <a88oi8$gb8$1...@ns.src.ricoh.co.jp>,
oh...@src.ricoh.co.jp (Junn Ohta) wrote:
>> なぜ、素直に int 型や、char *を使用しないで
>> BYTEなんか導入する
>なんでそんな設計をする人間をプロジェクトリーダーに
>したりするんだろう。
SJIS + ASCIIで構成された文字列とかを操作したりする時もそうで
しょうか?0x0041より0x8140の方が「小さい」ってのがどうも私の
感覚にそぐわないんです。文字コードは単なるビットパターンだか
ら、「小さい」ってことにどれだけ意味があるかってのはあります
けど。
という訳で、WORD使って文字コードを表現することが多いような気が
します。だから文字列はBYTE * を使うことがあります。これって、
ダメなのかなぁ。
もっとも、実際には、なるべくchar * で回して、文字コードが
問題になる局面で、局所的にBYTE * にキャストするって使い方か、
文字列自体を std::vector<SomeCharClass> みたいに使うほうが
多いですが。
他にも、char * を使う局面って、「それが文字列であって'\0'で
終わっている」という刷り込み(?)があるので、「単なるバイナリ
データで、'\0'で終わっているとは限らない」ということを明示
したい時にも使うような気がします。それは「BINARYって型を別途
宣言しろ」ってのは分かるんですけど。
あとMacOS 8/9だと、APIが受け入れてくれる文字列のフォーマットが
Pascal文字列なものがかなりあるので、unsigned charを使わざるを
得ないってのはあります。(それだけの理由で BYTE を typedef
しないけど。)
>> 質問2:
>> なぜ、整数型 int を記述すべきところで
>> char LoopCnt ;
>> char i ;
>> と、char を使用する人が後を絶たないのだろう
>
>会社内部で拡大再生産しているようなよっぽど間抜けな
>ところでないかぎり、そんな人はすでに絶滅しているの
>ではないかと思います。:-)
ループカウンタを char にする意味はないのは同感です。ちょっと話題が
ずれて申し訳ないのですが、この話を読んだ直後、頭に浮かんだのは
void foo(int * a)
{
int i; //(*1)
while (何かの条件) {
// i に関する操作
a[i] = …; // (*2)
}
}
なんてコードの場合、i == -1 の時に、(*2)の部分をデバッガで追っかけて
いても foo() の呼び出されたコンテキストによっては、間違いじゃない
可能性もあるわけです。でも(*1)部分が "unsigned int i" とかだったら、
配列に対するとてつもなく大きな index になるわけで、どこかで間違いが
起きていることが分かりやすい…なんて考えていたことがあります。
これについてはどうお考えになりますか?
# 今は素直に int 使ってます。^_^;
---------
山村 隆志 「debugは3歩後退、2歩前進、いつまでたっても終らない」
e-mail : vy...@janis.or.jp
WWW page : http://www.janis.or.jp/users/vyama/
>>そこまでわかってるなら簡単
>>unsigned char の 0xFF は 255
>>signed char の 0xFFは -1
>>で処理されてるからです。
> 簡単ですか?じゃあ 255 と -1 との違いは?
> (signed char)0xff と (unsigned char)0xff との扱いの違いな
>んて実装依存なんで、処理系によっては全く同じ結果が得られるこ
>とだってあり得ます。
> 多分そういう処理系は ANSI C は満たさないでしょうけど。
char が 9 ビット以上の処理系なら、どちらも同じ結果(255)になり
ますが、そのような処理系で C の規格を満たす処理系は多いですよ。
#「そのような処理系」が多くないという話はありますが、、、
--
片山@PFU
> 32BIT-CPUにおいて、
> 以下の出力と理由を述べよ
> printf("%x\n",(short)0xFFFF) ;
short が 16 ビット以下の処理系(これは規格に反しません)なら未定
義動作になりますから、どんな結果でもありですね。
--
片山@PFU
In article <KATE.02A...@flash.tokyo.pfu.co.jp>,
char が 9 ビット未満なら、(signed char)0xff は未定義動作ですから、
どんな結果になっても規格に反しません。したがって、両者が同じ値に
なっても規格に反しません。
# 8 ビット未満なら、別件で規格を満たさなくなりますが、、、
--
片山@PFU
> 32BIT-CPUにおいて、
> 以下の出力と理由を述べよ
>
> printf("%x\n",(short)0xFFFF) ;
もちろんimplementation definedですよね。
多くの処理系では ffffffff だったり ffff だったりしますが、他でもかまわ
ない。TIの320C3xシリーズとかだと、intもshortもcharも32ビットなので
ffffになるでしょう。
前田敦司
> char が 9 ビット未満なら、(signed char)0xff は未定義動作ですから、
undefined behaviorでもunspecified behaviorでもなく、
implementation definedでは(6.3.1.3)。
> どんな結果になっても規格に反しません。したがって、両者が同じ値に
> なっても規格に反しません。
この結論には影響しませんが。
前田敦司
> 現代の32BIT以上のCPUにおいて、
> なぜ、素直に int 型や、char *を使用しないで
> BYTEなんか導入する
> プロジェクトが存在するんだろう?
「素直に」というのを無視すれば、メモリの節約が必要な場合はあるでしょう
ね。組み込みに限らず、例えば画像・音声・信号処理などで「0~255までの値
を大量に使う」場合とか。(今ならuint8_tやuint_least8_tとかを使うべきか?)
> なぜ、整数型 int を記述すべきところで
> char LoopCnt ;
> char i ;
> と、char を使用する人が後を絶たないのだろう
「intを記述すべきところで」と言われると、すでに「charを使うのが間違い」
という答が質問に入ってしまっているみたいですが、
・特定のターゲット環境と仕様からcharで充分(charの方が良い)場合
・どんな(ISO準拠の)環境でも仕様からcharで充分(charの方が良い)場合
もありえる...かなあ。
まあ、「charで充分」は良いとして、「charの方が良い」理由としては、メモ
リの節約以外に思いつきませんね。その場合、最近の処理系ならint_least8_t
とかを使った方が意図がはっきりしますね。
「今回のターゲット(C規格でいう所のbyteが8bit)では、カウンタも含めて
少しでもメモリ使用量を削りたい。そのため、int_least8_t ですむところは
全てそれを使え。32bit CPUだけどalignmentは1 byte単位にしろ。
int_least8_t だと長いのでbyteと呼べ。」とか。
Takashi Yamamura <vy...@janis.or.jp> writes:
> SJIS + ASCIIで構成された文字列とかを操作したりする時もそうで
> しょうか?0x0041より0x8140の方が「小さい」ってのがどうも私の
> 感覚にそぐわないんです。文字コードは単なるビットパターンだか
> ら、「小さい」ってことにどれだけ意味があるかってのはあります
> けど。
最近のライブラリ関数(マクロ)使っても大小比較いりますかね?
文字コード依存のコードがどうしても要っても、一回ライブラリ書いて閉じ込
めてしまえば普段のコードには出てこない気がしますが。
> という訳で、WORD使って文字コードを表現することが多いような気が
> します。だから文字列はBYTE * を使うことがあります。これって、
> ダメなのかなぁ。
WORDってwchar_tのことですか?
> もっとも、実際には、なるべくchar * で回して、文字コードが
> 問題になる局面で、局所的にBYTE * にキャストするって使い方か、
> 文字列自体を std::vector<SomeCharClass> みたいに使うほうが
> 多いですが。
ですよね。charやwchar_tを大小比較したり配列の添字に使うのは、ポータブ
ルなプログラムではあんまり無いでしょうし、やるとしてもその近くで
unsignedにcast する方が楽でしょうね。
unsigned char *p = "abc";
とか
unsigned char *p = fgets(...);
とかも厳密にはundefined behaviorですから、普段はchar *にしとくのが楽で
すよね。
> 他にも、char * を使う局面って、「それが文字列であって'\0'で
> 終わっている」という刷り込み(?)があるので、「単なるバイナリ
> データで、'\0'で終わっているとは限らない」ということを明示
> したい時にも使うような気がします。それは「BINARYって型を別途
> 宣言しろ」ってのは分かるんですけど。
ふーむ。こういうときにハンガリアンなんですかねえ。本当は型じゃなくて
API の慣習なんだけど。
> ループカウンタを char にする意味はないのは同感です。ちょっと話題が
> ずれて申し訳ないのですが、この話を読んだ直後、頭に浮かんだのは
>
> void foo(int * a)
> {
> int i; //(*1)
> while (何かの条件) {
> // i に関する操作
> a[i] = …; // (*2)
> }
> }
>
> なんてコードの場合、i == -1 の時に、(*2)の部分をデバッガで追っかけて
> いても foo() の呼び出されたコンテキストによっては、間違いじゃない
> 可能性もあるわけです。でも(*1)部分が "unsigned int i" とかだったら、
> 配列に対するとてつもなく大きな index になるわけで、どこかで間違いが
> 起きていることが分かりやすい…なんて考えていたことがあります。
i == -1が間違いなのか間違いじゃないのか良く分からないんですけど、本当
に間違いじゃないかも...(本当にa[-1]を参照するのが正しかったりして)。
前田敦司
以下訂正。
"tabe" <ta...@mug.biglobe.ne.jp> wrote in message
news:a86v3t$l4$1...@bgsv5905.tk.mesh.ad.jp...
> > > BYTE i ;
> 中略(全文はこちら)
> http://news.dinf.ne.jp/news/fj/comp/lang/c/msg00200.html
>
> > ↓無限ループしません?
> > > for(i = 0 ; i < 0x100 ; i += 3) {
> しないでーーす。
> その前にゲロ吐いて、死にます。
HP-UX11.0では、無限ループしました。
"FUJIIHARA Keiichi" <kei...@fujihara.name> wrote in message
news:3ca7db8a$0$25163$44c9...@news2.asahi-net.or.jp...
> 藤原と申します。
> なんか呼ばれたかも ^^; 組み込み系です。
お待ちしておりました。
> > ROM:
> というわけで、8bit や 16bit のマイコンだと、char のほうがコードサ
> イズも小さくなることが多いですね。
32bit CPUの実際のところはどうでしょう。
>
> > RAM:
> こちらは、純粋に、変数が使う領域の問題ですね。
> 特に、8bit マイコンだとどうあがいてもアライメントの問題が発生しない
> (というか、アライメントはBYTE)ので、char の方が領域を食いません。
> 最近は、比較的 RAM 容量が多くなってきたので、そろそろ、int がデフォ
> ルトになってきてはいますね、私の場合でも。
8BIT,16BITは大変ですね。
自動変数で
char LoopCnt ; と記述する人は
スタックをケチってるみたいなんですが、
32BITーCPUでケチった効果があるのかな?てな疑問があります。
#BIT数関係無しで、RAM容量が重要なんですか。
>
> このような事情で、私の場合、組み込みのソフトの浮動小数点は未だに、float
> を使っています。
> これも、どちらかと言うと、double がデフォルトですよね、一般的には。
そうですよね。
UNIX上の小さいプログラムで、
floatをdouble に全部置換したら、
プログラム全体の処理速度が2倍高速になった事があります。
--
山口@福岡 <hy...@mx7.tiki.ne.jp>
>> 32BIT-CPUにおいて、
>> 以下の出力と理由を述べよ
>> printf("%x\n",(short)0xFFFF) ;
<m3zo0nu...@maedapc.cc.tsukuba.ac.jp> で前田さんが指摘された
ように implementation defined / implementation defined signal で
した。
--
片山@PFU
>> char が 9 ビット未満なら、(signed char)0xff は未定義動作ですから、
>undefined behaviorでもunspecified behaviorでもなく、
>implementation definedでは(6.3.1.3)。
はい、そうでした。(_ _;
型変換は、他の演算と違って結果型が表現できない値であっても未定義
動作ではありません。
ところで、“6.3.1.3”ということは C99 だと思いますが、C99 では、
implementation defined の値になるか、implementation defined
signal が発生します(その結果、値が得られないこともあり得ます)。
--
片山@PFU
> #ただし、構造体や配列は register に割り付けられないので別。
ちょうど話題になった「関数へのポインタ *だけ* を含む構造体」とかだと割
り当てられますね.
typedef struct status_t_ {
struct status_t_ (*fp) (void);
} status_t;
void
foo (void)
{
extern status_t initial_func (void);
status_t s = initial_func ();
do
s = (*s.fp) ();
while (s.fp);
}
x86-gcc
foo:
subl $12,%esp
call initial_func
.p2align 2,0x90
.L6:
call *%eax
testl %eax,%eax
jne .L6
addl $12,%esp
ret
v850-gcc
_foo:
jarl __save_r29_r31, r10
jarl _initial_func,r31
mov r10,r29
.L2:
jarl .+4,r31
add 4,r31
jmp r29
mov r10,r29
cmp r0,r29
bne .L2
jr __return_r29_r31
--
Kazuo Fox Dohzono / doh...@hf.rim.or.jp
> > というわけで、8bit や 16bit のマイコンだと、char のほうがコードサ
> > イズも小さくなることが多いですね。
>
> 32bit CPUの実際のところはどうでしょう。
CISC だとメモリ参照も演算も専用命令があったりしてほとんど変わらないと
思います. ただ, gcc だと関数呼び出しがネックで, 呼ぶ側も呼ばれた側も律
儀に上位 24 ビットをクリアする (多くの場合) 余分な命令が出てしまいます
が, これはコンパイラが賢くなれば終わる話ですね.
# それとも何か見落としてる?
> 自動変数で
> char LoopCnt ; と記述する人は
> スタックをケチってるみたいなんですが、
> 32BITーCPUでケチった効果があるのかな?てな疑問があります。
普通 push/pop はマシンワード単位なので効果はないでしょう.
> UNIX上の小さいプログラムで、
> floatをdouble に全部置換したら、
> プログラム全体の処理速度が2倍高速になった事があります。
# 暗黙の型変換バリバリだったとか….
m88k の FPU は, たとえば乗算のオペランド二つと結果の計三つそれぞれに
単精度/倍精度が指定できて好きでした (ニュートン法の最初の方で入力は単
精度で出力を倍精度で得るとか出来て便利).
This message is reply to tabe - san
(Subject was : Re: 日本人のBYTEへの異常な愛情)
Message-ID: <a8akcm$2lv$2...@bgsv5905.tk.mesh.ad.jp>
in Tue, 2 Apr 2002 06:38:22 +0900 ...
>
> > > ROM:
> > というわけで、8bit や 16bit のマイコンだと、char のほうがコードサ
> > イズも小さくなることが多いですね。
>
> 32bit CPUの実際のところはどうでしょう。
32bit でも、「あたかも int に拡張したように」するだけなら、singned 同士
unsigned 同士なら、int に拡張せずに処理する場合もありえますね。
その場合なら、まあ、コードが長くはならないでしょう。
>
> #BIT数関係無しで、RAM容量が重要なんですか。
RAM 容量が潤沢になれば、わざわざ数値の意味で char を使わないのが普通だと
は思いますが。
--
* address na...@sep.email.ne.jp is also availableness yet.
_/ -- Last 1898 hours until 2002 World Cup final (02 Apl @395) ------
_/ FUJIHARA Keiichi
_/ E-Mail : kei...@fujihara.name <or> na...@qua.net
_/ URL : http://www.keiichi.fujihara.name/
--------------------------------------------+----- Luna Phase 19.91 --
This message is reply to Kazuo Fox Dohzono - san
(Subject was : Re: 日本人のBYTEへの異常な愛情)
Message-ID: <a8bku9$20ra$1...@news2.rim.or.jp>
in 02 Apr 2002 15:28:49 GMT ...
> > UNIX上の小さいプログラムで、
> > floatをdouble に全部置換したら、
> > プログラム全体の処理速度が2倍高速になった事があります。
>
> # 暗黙の型変換バリバリだったとか….
定数リテラルを使ったら暗黙の型変換発生。
math.h の関数も、ほとんど暗黙の型変換発生。
と、それはそれは、きっと大量の型変換が発生していたと思われます。
--
* address na...@sep.email.ne.jp is also availableness yet.
_/ -- Last 1898 hours until 2002 World Cup final (02 Apl @393) ------
_/ FUJIHARA Keiichi
_/ E-Mail : kei...@fujihara.name <or> na...@qua.net
_/ URL : http://www.keiichi.fujihara.name/
--------------------------------------------+----- Luna Phase 19.91 --
tabeさんの<a89r0v$g4u$1...@bgsv5906.tk.mesh.ad.jp>から
>田部です。
ども。お世話になります。
> じゃ、練習問題
> unisgned char uc = 0x80 ;
> signed char c = 0x80 ;
> printf("%x\n",uc) ;
> printf("%x\n",c) ;
> の出力と理由を述べよ。
80
fffff80
となります。理由は、16進数の80は二進数でかくと、
(10000000)_{2}となるので、unsigned は頭をゼロ
で埋めるのだけれども、signed は頭を1で埋めてしまう。
ちなみに、uc = 0x7f , c = 0x7f にしたら、
両方とも、
7f
7f
になりました。サインビットが立っていないから
同じ結果になる。
っであってますか。
> char って書いても
> signed char の事を意味しない。
> つまり
> char 型には
> signed char (符号有りCHAR)
> unsigned char (符号無しCHAR)
> char (ピュアCHAR=まさに文字を表すためのCHAR)
> の3種類がある。
こっちは理解しました。
多くの方々にご教授頂き、誠にありがとうございました。
--
hidenori mailto:miyo...@d1.dion.ne.jp
田部さんの記事<a89r0v$g4u$1...@bgsv5906.tk.mesh.ad.jp>から
> int って書くと、
> signed int の事を意味する。
> でも、
> char って書いても
> signed char の事を意味しない。
> つまり
> char 型には
> signed char (符号有りCHAR)
> unsigned char (符号無しCHAR)
> char (ピュアCHAR=まさに文字を表すためのCHAR)
> の3種類がある。
片仮名で書いてあるし、そう大した問題でもないと思うのですが、
多くの場合、「ピュアCHAR」ではなく"plain char"と書きませんか。
("pure char"だとsignedやunsignedが不純であるかの様に聞こえて
しまいます。plainは「修飾無しの、素の、そのままの」という意
味です。)
それと引用した記事は読み様によってはsigned char, unsigned
char以外に独立した型としてcharがある様に読めなくもないです。
符号付き、符号無しに加え、文字を表わす為のchar型があるかの様
に読めなくもない。(C++にはあるけれど。)
要らぬお世話かもしれませんが、誤解されぬ様に注意した方が良
いと思います。
> char って書いても
> signed char の事を意味しない。
部分否定には読めない人も居ると思います。
--
椎野 裕樹 <yu...@cds.ne.jp>
> 片仮名で書いてあるし、そう大した問題でもないと思うのですが、
> 多くの場合、「ピュアCHAR」ではなく"plain char"と書きませんか。
これは同意ですが、
> それと引用した記事は読み様によってはsigned char, unsigned
> char以外に独立した型としてcharがある様に読めなくもないです。
これもややこしいんですが、C99の規格書を読むと
[#15] The three types char, signed char, and unsigned char
are collectively called the character types. The
implementation shall define char to have the same range,
representation, and behavior as either signed char or
unsigned char.35)
つまり、``plain'' charはsigned charかunsigned charのどちらかと全く同
じ範囲・表現・ふるまいを持つ(どちらと同じかは処理系定義である)んですが、
いずれかと「同じ型」かというと、脚注35に
... Irrespective of the choice
made, char is a separate type from the other two and is
not compatible with either.
とあるので、char, signed char, unsigned charはそれぞれ「別の型」なんで
す。
前田敦司
> 片仮名で書いてあるし、そう大した問題でもないと思うのですが、
> 多くの場合、「ピュアCHAR」ではなく"plain char"と書きませんか。
これは同意ですが、
> それと引用した記事は読み様によってはsigned char, unsigned
> char以外に独立した型としてcharがある様に読めなくもないです。
これもややこしいんですが、C99の規格書を読むと
[#15] The three types char, signed char, and unsigned char
are collectively called the character types. The
implementation shall define char to have the same range,
representation, and behavior as either signed char or
unsigned char.35)
つまり、``plain'' charはsigned charかunsigned charのどちらかと全く同
じ範囲・表現・ふるまいを持つ(どちらと同じかは処理系定義である)んですが、
いずれかと「同じ型」かというと、脚注35に
... Irrespective of the choice
made, char is a separate type from the other two and is
not compatible with either.
とあるので、char, signed char, unsigned charはそれぞれ「別の型」なんで
す。
# 私も知らんかった...「どちらかと同じ型(だけどどちらと同じかは仮定で
# きない)」と思ってた。
前田敦司
In article <m3vgb9v...@maedapc.cc.tsukuba.ac.jp>, MAEDA Atusi wrote:
この plain char の話は,char の default が signed と unsigned の処理
系の両方が有った/る,という現実を追認するためであると理解していま
す.したがって,,,
>これもややこしいんですが、C99の規格書を読むと
> [#15] The three types char, signed char, and unsigned char
> are collectively called the character types. The
> implementation shall define char to have the same range,
> representation, and behavior as either signed char or
> unsigned char.35)
>つまり、``plain'' charはsigned charかunsigned charのどちらかと全く同
>じ範囲・表現・ふるまいを持つ(どちらと同じかは処理系定義である)んですが、
ここは素直に読んで,
>いずれかと「同じ型」かというと、脚注35に
> ... Irrespective of the choice
> made, char is a separate type from the other two and is
> not compatible with either.
>とあるので、char, signed char, unsigned charはそれぞれ「別の型」なんで
>す。
おっしゃる通りで,型としては別の型になるわけですが,これは「char が
どちらかと compatible だと思ってはいけない」(つまりプログラマに対す
る戒め)と理解するのがいいと思います.
># 私も知らんかった...「どちらかと同じ型(だけどどちらと同じかは仮定で
># きない)」と思ってた。
実質的にはそれで正しいと思いますが,規格としては,それはちょっ
と,,,採用できませんよねぇ.
#勘違い等ありましたらよろしく (_ _).>ALL
--
Hideki Kato <mailto:ka...@pop12.odn.ne.jp>
-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
Check out our new Unlimited Server. No Download or Time Limits!
-----== Over 80,000 Newsgroups - 19 Different Servers! ==-----
# 重箱の隅ですが、、、
In article <a8bku9$20ra$1...@news2.rim.or.jp>
doh...@hf.rim.or.jp (Kazuo Fox Dohzono) writes:
> > 自動変数で
> > char LoopCnt ; と記述する人は
> > スタックをケチってるみたいなんですが、
> > 32BITーCPUでケチった効果があるのかな?てな疑問があります。
>
> 普通 push/pop はマシンワード単位なので効果はないでしょう.
ローカル変数をスタックに割り付ける場合、普通 push/pop なんて
使わないと思います。少なくとも、m68k の場合は link/unlk で
ローカル変数を全部まとめて割り付けます。
なので、char が複数並べばスタック節約の効果がある可能性はあります。
(もっとも、register 割り付けの場合には関係ないけど...)
# もちろん、ふだんはスタック消費なんてほとんど気にしません。
# というか、気にする場合には char か int かなんてレベルじゃ
# 済まないというか...
ほし
> おっしゃる通りで,型としては別の型になるわけですが,これは「char が
> どちらかと compatible だと思ってはいけない」(つまりプログラマに対す
> る戒め)と理解するのがいいと思います.
ええ、そうなんですけど、「compatibleでない」とすると他の定義から
char *とunsigned char *も、またchar *とsigned char *もcompatibleでない
ことになりますから、<m3u1qvu...@maedapc.cc.tsukuba.ac.jp>で書いた
通り
unsigned char *p = "abc";
とか
unsigned char *p = fgets(...);
は(処理系定義どころではなくて)未定義動作になってしまいます。これをエラー
とする処理系があるかどうかは知りませんが、なかなか厳しいですよね。(gcc
-pedanticだと検出します。)
> ># 私も知らんかった...「どちらかと同じ型(だけどどちらと同じかは仮定で
> ># きない)」と思ってた。
>
> 実質的にはそれで正しいと思いますが,規格としては,それはちょっ
> と,,,採用できませんよねぇ.
いやー...
#include <limits.h>
#define CHAR_IS_SIGNED CHAR_MIN
#if CHAR_IS_SIGNED
/* char は signed char と「同じ」 */
#define to_ustr(x) ((unsigned char *)(x))
#define to_sstr(x) (x)
#define to_str(x) ((char *)(x))
#else
/* char は unsigned char と「同じ」 */
#define to_ustr(x) (x)
#define to_sstr(x) ((signed char *)(x))
#define to_str(x) (x)
#endif
なんてのはアリかと思っていたのですが、この規格だとダメなんですねえ...
unsigned char *u = to_ustr("abc");
signed char *s = to_sstr("abc");
if (strcmp(to_str(u), to_str(s))) ...
なんてのは必ず未定義動作になってしまう。
# C規格triviaには格好の課題かも。
前田敦司
"Hoshi Takanori" <ho...@sra.co.jp> wrote in message
news:HOSHI.02A...@ext54.sra.co.jp...
> ほしです。
> # もちろん、ふだんはスタック消費なんてほとんど気にしません。
> # というか、気にする場合には char か int かなんてレベルじゃ
> # 済まないというか...
> ほし
うん。
スタックオーバーフローの悪者は、
複合体(構造体とか、配列とか、構造体配列)
の自動変数だと思っているのですが、
スタックオーバーフローの経験者の皆様、
原因は何で、
どの様に対処されましたか?
―――――――――――――――――――――――――――
deki Kato" <ka...@pop12.odn.ne.jp> wrote in message
news:3caa4a14$1...@binarykiller.newsgroups.com...
> 加藤@ODNです.
> ># 私も知らんかった...「どちらかと同じ型(だけどどちらと同じかは仮定で
> ># きない)」と思ってた。
> 実質的にはそれで正しいと思いますが,規格としては,それはちょっ
> と,,,採用できませんよねぇ.
> #勘違い等ありましたらよろしく (_ _).>ALL
む、む、難しすぎるので、
キャスト地獄に落ちている人の、
グループリーダに解る様に書いてください。
#include <string.h>
int main()
{
unsigned char uc[1024] ;
signed char sc[1024] ;
~~~~
return strcmp(uc,sc) ;
}
Solaris2.6も、HP-UX11.0も、EWS4800も、
コンパイラは皆、文句を言った。
#文字なんだから、符号付も無しも、ないだろう、
#なんで、いらんunsigned/sigend を書くの?
#ってな、感じで。
反応がかんばしくないですね。やっぱりふつうの人はそ
んな危機感はもってないんじゃないですか? 私も、少な
くともUNIXではスタックオーバーフローなんてほとんど
見たことないですよ。
というか、設計時に各モジュールがどれくらいメモリー
を使うか検討するでしょう? で、プログラム全体で関数
がどんな具合に呼び出されて、いちばん深いところでど
んな関数がどれだけネストされるか検討して、そのとき
スタックがどれだけ使われるかについても、おおよその
ところは見積もられるわけです。
構文解析やデータ検索ではツリーやリストの構造を扱い
ますが、そのときは再帰がどれだけ深まる可能性がある
かについても検討しますよね。いずれにしても設計時に
見積もり可能なわけですから、それを仕様にしておけば
よいだけの話でしょう。
私が扱ってきたプログラムでは、スタック消費はふつう
数十KB~数百KB程度です。UNIXならオーバーフローを気
にするレベルではないですね。
「複合体の自動変数」についても、それが必要ならサイ
ズを気にしながら使うだけだし、あまり大きくなるよう
ならデータレイアウトやアルゴリズムを検討しなおして
納得できるサイズにおさまるようにするだけです。
--
太田純(Junn Ohta) (株)リコー/新横浜事業所
oh...@sdg.mdd.ricoh.co.jp
In article <a8f3p2$a28$1...@bgsv5905.tk.mesh.ad.jp>, tabe wrote:
>
>素CHARを、純CHARと2年間思っていた、
>いいだしっぺの、田部です。
>
>deki Kato" <ka...@pop12.odn.ne.jp> wrote in message
>news:3caa4a14$1...@binarykiller.newsgroups.com...
>> 加藤@ODNです.
>> ># 私も知らんかった...「どちらかと同じ型(だけどどちらと同じかは仮定で
>> ># きない)」と思ってた。
>> 実質的にはそれで正しいと思いますが,規格としては,それはちょっ
>> と,,,採用できませんよねぇ.
>> #勘違い等ありましたらよろしく (_ _).>ALL
>
>む、む、難しすぎるので、
> キャスト地獄に落ちている人の、
> グループリーダに解る様に書いてください。
私は田部さんがどの様な知識をお持ちか存じませんので,どう書けば田部さ
んに解るかが解りません.何が/どこがどう解らないのかを書いて下さい.
>#include <string.h>
>int main()
>{
> unsigned char uc[1024] ;
> signed char sc[1024] ;
> ~~~~
> return strcmp(uc,sc) ;
>}
>Solaris2.6も、HP-UX11.0も、EWS4800も、
> コンパイラは皆、文句を言った。
>
>#文字なんだから、符号付も無しも、ないだろう、
>#なんで、いらんunsigned/sigend を書くの?
>#ってな、感じで。
C言語の歴史を最初から勉強すれば,char に signed/unsigned があるのも
納得できるでしょうし,私が上に書いた文章も理解できるようになると思い
ます.
でも、文字型(char, unsigned char, signed char)は単に整数型の一種ですよ
ね。文字定数'a'の型はint型ですし...
ですから「符号付きも無しも」ありますよね。
これを気にしないと、
char buf[1024];
int c, i, n;
n = fread(buf, 1, sizeof(buf), fp);
rewind(fp);
for (i = 0; (c = getc(fp)) != EOF && i < n; i++) {
/* あれ、buf[i]とcが等しくない! */
}
とか悩む羽目に...
Hideki Kato <ka...@pop12.odn.ne.jp> writes:
> C言語の歴史を最初から勉強すれば,char に signed/unsigned があるのも
> 納得できるでしょうし,私が上に書いた文章も理解できるようになると思い
> ます.
signedという予約語はsigned charと書くためだけに作られたものだと理解し
てます。もっとはっきり言っちゃえば、charをunsignedにしてたMS-DOS上の多
くのCが邪魔をしなければ、intやshortと同様に「charは符号付き」とすっき
りと決められた(で、signedという予約語を追加する必要もなかった)だろうに、
と思ってます。(charがunsignedだったプラットフォームは他にもありました
が、それくらいは符号付きに変えさせても良かったと思う。)
上みたいなコードを考えると、charが符号付きなのは鬱陶しいときもあります
が、「符号付きかどうかわからん」「signed charでもunsigned charでもない」
現状より余程ましですよね。
前田敦司
In article <m3y9g3t...@maedapc.cc.tsukuba.ac.jp>, MAEDA Atusi wrote:
>> In article <a8f3p2$a28$1...@bgsv5905.tk.mesh.ad.jp>, tabe wrote:
>> >#文字なんだから、符号付も無しも、ないだろう、
>> >#なんで、いらんunsigned/sigend を書くの?
>> >#ってな、感じで。
>
>でも、文字型(char, unsigned char, signed char)は単に整数型の一種ですよ
>ね。文字定数'a'の型はint型ですし...
>
>ですから「符号付きも無しも」ありますよね。
>
>これを気にしないと、
> char buf[1024];
> int c, i, n;
>
> n = fread(buf, 1, sizeof(buf), fp);
> rewind(fp);
> for (i = 0; (c = getc(fp)) != EOF && i < n; i++) {
> /* あれ、buf[i]とcが等しくない! */
> }
>とか悩む羽目に...
>
>Hideki Kato <ka...@pop12.odn.ne.jp> writes:
>
>> C言語の歴史を最初から勉強すれば,char に signed/unsigned があるのも
>> 納得できるでしょうし,私が上に書いた文章も理解できるようになると思い
>> ます.
>
>signedという予約語はsigned charと書くためだけに作られたものだと理解し
>てます。
私もそう理解しています.
>もっとはっきり言っちゃえば、charをunsignedにしてたMS-DOS上の多
>くのCが邪魔をしなければ、intやshortと同様に「charは符号付き」とすっき
>りと決められた(で、signedという予約語を追加する必要もなかった)だろうに、
>と思ってます。(charがunsignedだったプラットフォームは他にもありました
>が、それくらいは符号付きに変えさせても良かったと思う。)
私は MS-DOS より UTS の影響が大きかったと思っていたのですが,どうな
んでしょう?>知ってる人
説明: IBM の System360/370 にはレジスタ上のバイトを符号拡張する命令
が無く,(signed) char の実引数をスタックに積むときは引数一個毎に数ス
テップの命令が必要になります.このために UTS の標準の C compiler で
は char は unsigned でした.#これでどれだけ苦労したか...
>上みたいなコードを考えると、charが符号付きなのは鬱陶しいときもあります
>が、「符号付きかどうかわからん」「signed charでもunsigned charでもない」
>現状より余程ましですよね。
御意.#ANSI C の規格を決めてる連中もそう思っていることでしょう (^^;;).
> >deki Kato" <ka...@pop12.odn.ne.jp> wrote in message
> >news:3caa4a14$1...@binarykiller.newsgroups.com...
下記の件、
> 私は田部さんがどの様な知識をお持ちか存じませんので,どう書けば田部さ
> んに解るかが解りません.何が/どこがどう解らないのかを書いて下さい.
以下のところです。
> >> 実質的にはそれで正しいと思いますが,規格としては,それはちょっ
> >> と,,,採用できませんよねぇ.
結局、CHARの型は、
規格では
2つですか?
3つですか?
以下の私の表現を補足すると、
「英数字の文字列を扱うならば、unsigned/sigend はいらん」を追加します。
> > In article <a8f3p2$a28$1...@bgsv5905.tk.mesh.ad.jp>, tabe wrote:
> > >#文字なんだから、符号付も無しも、ないだろう、
> > >#なんで、いらんunsigned/sigend を書くの?
> > >#ってな、感じで。
下記の前田さんの例は
> ですから「符号付きも無しも」ありますよね。
> これを気にしないと、
> char buf[1024];
> int c, i, n;
> n = fread(buf, 1, sizeof(buf), fp);
> rewind(fp);
> for (i = 0; (c = getc(fp)) != EOF && i < n; i++) {
> /* あれ、buf[i]とcが等しくない! */
> }
> とか悩む羽目に...
文字列ではなくて、HEXデータの処理を想定されてますよね?。
HEXデータの処理であれば、
おっしゃる通り、符号を意識しなければならないと思います。
> 上みたいなコードを考えると、charが符号付きなのは鬱陶しいときもあります
> が、「符号付きかどうかわからん」「signed charでもunsigned charでもない」
> 現状より余程ましですよね。
unsigned char を使用するのは全角文字を使用する時だと思うのですが、
wchar_tはどんな時、どう使うのでしょう?
#wchar_tの使用例が手持ちの本にありません。
ここら辺、前田さん詳しそうなので、質問
char *jap = ”123漢字abc" ;
の半角、全角混在の文字列を
wchar_t を使用して、
1
2
3
漢
字
a
b
c
と、縦書きする方法(プログラム)をよろしければ教えて下さい。
"Junn Ohta" <oh...@src.ricoh.co.jp> wrote in message
news:a8gggf$336$1...@ns.src.ricoh.co.jp...
> 反応がかんばしくないですね。やっぱりふつうの人はそ
> んな危機感はもってないんじゃないですか?
あんまり受けませんね。
> 私も、少なくともUNIXではスタックオーバーフローなんてほとんど
> 見たことないですよ。
私もUNIXで開発してるので、実は経験した事が無いです。
実験的に、以下のプルグラムを走らせたら
int main()
{
char buf[1024] ;
mai........................... /* 全部書くと真似る人がでるので省略*/
UNIXが落ちましたが。
> というか、設計時に各モジュールがどれくらいメモリー
> を使うか検討するでしょう? で、プログラム全体で関数
> がどんな具合に呼び出されて、いちばん深いところでど
> んな関数がどれだけネストされるか検討して、そのとき
> スタックがどれだけ使われるかについても、おおよその
> ところは見積もられるわけです。
これは、規模見積もりに輪をかけて難しいです。
UNIXコマンドCFLOWの出力の横に
1関数のスタック量を記述して、スタック量を加算していく
ツールを作ってますが、
関数ポインタとかまでは追えないので、
あくまで概算値の目安しか、わからなかったです。
> 「複合体の自動変数」についても、それが必要ならサイ
> ズを気にしながら使うだけだし、あまり大きくなるよう
> ならデータレイアウトやアルゴリズムを検討しなおして
> 納得できるサイズにおさまるようにするだけです。
組込み系におけるスタックオーバーフロー対策が難しいのは、
スタックサイズの見積もりの難しさにあると思います。
余談ですが、以下のコードでは
myfunc() {
if(X) {
char buf[1024] ;
} else if(Y) {
char buf[1024] :
} else if(Z) {
char buf[1024] ;
}
}
ブロックが違うので、
スタック消費が 1024 かと思ったら、
1024 * 3 消費していました。
#処理系に依存する事なのでしょうけれども。
設計の話ですから概算でいいんですよ。プロトタイプの
段階でどれだけスタックを消費しているか調べたかった
ら、いちばん深く呼ばれる関数の中でスタック上の変数
のアドレスを記録しておいて、実行開始時のスタックポ
インターとあとで比較することもできますし。
もっと細かい情報が必要になるのは、設計時の予想より
スタック消費が大きくて、もっと小さくしなければなら
なくなった場合ぐらいでしょうけど、そういう場合こそ
設計時のモジュール単位の見積もりが役に立つわけです。
> 余談ですが、以下のコードでは
> myfunc() {
> if(X) {
> char buf[1024] ;
> } else if(Y) {
> char buf[1024] :
> } else if(Z) {
> char buf[1024] ;
> }
> }
> ブロックが違うので、
> スタック消費が 1024 かと思ったら、
> 1024 * 3 消費していました。
> #処理系に依存する事なのでしょうけれども。
田部さん、次のコードの意味はわかりますか?
if (cond_X) {
char buf_X[1024];
...
goto block_Y;
...
} else if (cond_Y) {
char buf_Y[1024];
...
block_Y:
...
> unsigned char を使用するのは全角文字を使用する時だと思うのですが、
> wchar_tはどんな時、どう使うのでしょう?
> #wchar_tの使用例が手持ちの本にありません。
> ここら辺、前田さん詳しそうなので、質問
> char *jap = ”123漢字abc" ;
> の半角、全角混在の文字列を
> wchar_t を使用して、
>1
>2
>3
>漢
>字
>a
>b
>c
> と、縦書きする方法(プログラム)をよろしければ教えて下さい。
・最初から wchar_t の場合
-----------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
int
main(int argc, char **argv)
{
wchar_t *wcs = L"123漢字abc";
setlocale(LC_ALL, "");
while (*wcs != '\0') {
printf("%C\n", *wcs++);
}
return 0;
}
-----------------------------------------
・char* から一括変換して処理する場合
-----------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
int
main(int argc, char **argv)
{
char *jap = "123漢字abc";
setlocale(LC_ALL, "");
{
int len = mbstowcs(NULL, jap, 0);
wchar_t *wcs = malloc(sizeof *wcs * (len + 1));
mbstowcs(wcs, jap, len);
while (*wcs != '\0') {
printf("%C\n", *wcs++);
}
free(wcs);
}
return 0;
}
-----------------------------------------
・char* から一文字づつ変換して処理する場合
-----------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int
main(int argc, char **argv)
{
char *jap = "123漢字abc";
setlocale(LC_ALL, "");
{
int len = strlen(jap);
int ret;
wchar_t wc;
while (len > 0 && (ret = mbtowc(&wc, jap, len)) > 0) {
printf("%C\n", wc);
jap += ret; len -= ret;
}
}
return 0;
}
-----------------------------------------
よーするに、いわゆる全角半角関係なく、一文字 = wchar_t 一つということ
になります。3つ目の例のように、なにかしら処理するたびに変換をしていると
効率が著しく悪くなるので、普通は、入出力段階のみで 多バイト <-> ワイド
変換を行い、内部では wchar_t のみで処理するように書きます。
Windows プログラムの場合、char でなく_TCHAR を使うようにしておけば、
コンパイル時に -DUNICODE するとその実体が全部 wchar_tになります。
ちなみに、Java の char 型は、C の wchar_t型に該当します
そして、C の char 型に該当するのは byte 型です。ある意味とても素直(^^;
--
渡邊剛 (Watanabe,Go) g...@dsl.gr.jp / g...@denpa.org
>In article <m3y9g3t...@maedapc.cc.tsukuba.ac.jp>, MAEDA Atusi wrote:
>>signedという予約語はsigned charと書くためだけに作られたものだと理解し
>>てます。
>私もそう理解しています.
そう言い切ってしまうとビットフィールドの立場が無くなってしまうよ
うな気が、、、
>>もっとはっきり言っちゃえば、charをunsignedにしてたMS-DOS上の多
>>くのCが邪魔をしなければ、intやshortと同様に「charは符号付き」とすっき
>>りと決められた(で、signedという予約語を追加する必要もなかった)だろうに、
>>と思ってます。(charがunsignedだったプラットフォームは他にもありました
>>が、それくらいは符号付きに変えさせても良かったと思う。)
>私は MS-DOS より UTS の影響が大きかったと思っていたのですが,どうな
>んでしょう?>知ってる人
どっちの処理系の方が多く使われたかは存じませんが、S/370 の方が先
でしたから、影響が大きかったかも知れません。
>説明: IBM の System360/370 にはレジスタ上のバイトを符号拡張する命令
>が無く,(signed) char の実引数をスタックに積むときは引数一個毎に数ス
>テップの命令が必要になります.このために UTS の標準の C compiler で
>は char は unsigned でした.#これでどれだけ苦労したか...
命令数で言えば、どちらも最少 2命令ですね。
unsigned
xr Rx,Rx
ic Rx,...
signed
icm Rx,8,...
sra Rx,24
もっとも、符号付は、
ic Rx,...
sll Rx,24
sra Rx,24
の方が速いと思います。
S/370 で char が符号無しなのは、文字セットが EBCDIC のためでしょ
う。K&R の時代は「標準文字集合の要素は非負」という規定がありまし
た。
ANSI C では直接的な表現はなくなりましたが、S/370 で「文字集合が
EDCDIC である」というためには、やはり char を符号無しとする必要
があります。
# char を 16 ビットにして符号付にするという実装はアリですが、使
#う人がいないでしょう(^^;
>>上みたいなコードを考えると、charが符号付きなのは鬱陶しいときもあります
>>が、「符号付きかどうかわからん」「signed charでもunsigned charでもない」
>>現状より余程ましですよね。
>御意.#ANSI C の規格を決めてる連中もそう思っていることでしょう (^^;;).
早く EBCDIC が世の中から消えて欲しいと思っているかも?
--
片山@PFU
>> ブロックが違うので、
>> スタック消費が 1024 かと思ったら、
>> 1024 * 3 消費していました。
>> #処理系に依存する事なのでしょうけれども。
>田部さん、次のコードの意味はわかりますか?
> if (cond_X) {
> char buf_X[1024];
> ...
> goto block_Y;
> ...
> } else if (cond_Y) {
> char buf_Y[1024];
> ...
> block_Y:
> ...
> }
太田さんが主張されたいことが分からないのですが、、、
4 An obect … has automatic duration.
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.
ですから、goto block_Y; を実行すると buf_X の寿命は終ってしまい
ます。一方、buf_X が生きている間は buf_Y の寿命が始まっていませ
ん(日本語にすると何か変(^^;)から、両者を同じ領域に割り当てるこ
とは可能です。
--
片山@PFU
> 下記の前田さんの例は
> > ですから「符号付きも無しも」ありますよね。
> > これを気にしないと、
> > char buf[1024];
> > int c, i, n;
> > n = fread(buf, 1, sizeof(buf), fp);
> > rewind(fp);
> > for (i = 0; (c = getc(fp)) != EOF && i < n; i++) {
> > /* あれ、buf[i]とcが等しくない! */
> > }
> > とか悩む羽目に...
> 文字列ではなくて、HEXデータの処理を想定されてますよね?。
> HEXデータの処理であれば、
> おっしゃる通り、符号を意識しなければならないと思います。
別にHEXデータの処理を想定していると言うわけではありませんけど...
(octalデータだったりして :-)
freadじゃなくてfgetsでも、getcのループでも同じことが起きます。
> unsigned char を使用するのは全角文字を使用する時だと思うのですが、
> wchar_tはどんな時、どう使うのでしょう?
> #wchar_tの使用例が手持ちの本にありません。
>
> ここら辺、前田さん詳しそうなので、質問
ぜんぜん詳しくありませんので、渡邊さんにおまかせしますが、
unsigned charと多バイト文字はあんまり関係ないと思います。
(multibyte関係のライブラリ関数はunsigned char *でなくてchar *を引数に
取ります。)
> ちなみに、Java の char 型は、C の wchar_t型に該当します
> そして、C の char 型に該当するのは byte 型です。ある意味とても素直(^^;
素直ですよね。byte, short, int, long という整数型と別にcharがあって、
charだけはunsigned。
もっと思いきって変えるなら(他の多くの言語のように)数値じゃない「文字デー
タ」という概念を付け加えるんでしょうね。
前田敦司
> 下記の前田さんの例は
> > ですから「符号付きも無しも」ありますよね。
> > これを気にしないと、
> > char buf[1024];
> > int c, i, n;
> > n = fread(buf, 1, sizeof(buf), fp);
> > rewind(fp);
> > for (i = 0; (c = getc(fp)) != EOF && i < n; i++) {
> > /* あれ、buf[i]とcが等しくない! */
> > }
> > とか悩む羽目に...
> 文字列ではなくて、HEXデータの処理を想定されてますよね?。
> HEXデータの処理であれば、
> おっしゃる通り、符号を意識しなければならないと思います。
別にHEXデータの処理を想定していると言うわけではありませんけど...
(octalデータだったりして :-)
freadじゃなくてfgetsでも、getcのループでも同じことが起きます。
> unsigned char を使用するのは全角文字を使用する時だと思うのですが、
> wchar_tはどんな時、どう使うのでしょう?
> #wchar_tの使用例が手持ちの本にありません。
>
> ここら辺、前田さん詳しそうなので、質問
ぜんぜん詳しくありませんので、渡邊さんにおまかせしますが、
unsigned charと多バイト文字はあんまり関係ないと思います。
(multibyte関係のライブラリ関数はunsigned char *でなくてchar *を引数に
取ります。)
g...@denpa.org (Go Watanabe) writes:
> ちなみに、Java の char 型は、C の wchar_t型に該当します
> そして、C の char 型に該当するのは byte 型です。ある意味とても素直(^^;
素直ですよね。byte, short, int, long という整数型と別にcharがあって、
>> 文字列ではなくて、HEXデータの処理を想定されてますよね?。
>> HEXデータの処理であれば、
>> おっしゃる通り、符号を意識しなければならないと思います。
>
>別にHEXデータの処理を想定していると言うわけではありませんけど...
>(octalデータだったりして :-)
>freadじゃなくてfgetsでも、getcのループでも同じことが起きます。
関連した余談。
is* 関数群の引数は int であり、有効な引数は EOF と unsigned char の範囲
ということになっていて、それ以外の値を入れた場合には、どんな値が
帰ってくるか未定義です。
というわけで、(signed) char でデータを扱っているものを is* に通す時には、
必ず unsigned char にキャストしてから渡すようにコードを書かないといけない
わけなのですが、そうなってないプログラムはとても多く、そのせいで 8bit
スルーになってないものが、今でもかなり存在していたりします。
さらなる余談。is* はテーブルで実装されていることが多いわけですが、
glibc の実装は、このテーブルがおもいっきり負側にはみでていて
(有効範囲: -127~255)、くらっと来たことがあります(苦笑)
いや、そりゃ、間違えているコードでも通るようになるかもしれんけど、
それは根本的に違うだろ……と(^^;
# Linux では動くものが、他のOSではなぜか動かない現象の原因の一つです。
けっこう微妙なんですけども...。(^^;
> ですから、goto block_Y; を実行すると buf_X の寿命は終ってしまい
> ます。一方、buf_X が生きている間は buf_Y の寿命が始まっていませ
> ん(日本語にすると何か変(^^;)から、両者を同じ領域に割り当てるこ
> とは可能です。
はい。
if (...) {
領域割り当て
} else {
領域割り当て
}
であっても必ずしも排他ではないので
{
領域割り当て
}
{
領域割り当て
}
と同じぐらいの手間はかかりますよ、という話です。
# それがどれくらいの手間か、というあたりは微妙かな
# と思ったので、それは話が先に進んでから追い追い書
# こうかな、と。:-)
In article <KATE.02A...@flash.tokyo.pfu.co.jp>, KATAYAMA Yoshio wrote:
>>私は MS-DOS より UTS の影響が大きかったと思っていたのですが,どうな
>>んでしょう?>知ってる人
>
>どっちの処理系の方が多く使われたかは存じませんが、S/370 の方が先
>でしたから、影響が大きかったかも知れません。
>
>>説明: IBM の System360/370 にはレジスタ上のバイトを符号拡張する命令
>>が無く,(signed) char の実引数をスタックに積むときは引数一個毎に数ス
>>テップの命令が必要になります.このために UTS の標準の C compiler で
>>は char は unsigned でした.#これでどれだけ苦労したか...
>
>命令数で言えば、どちらも最少 2命令ですね。
>
>unsigned
> xr Rx,Rx
> ic Rx,...
#これは2命令で6バイト.
>signed
> icm Rx,8,...
> sra Rx,24
#これも2命令で6バイト.
あ,ICM (insert characters under mask) は System360 には無かった
んです(AI (add character immediate),CSD (compare and swap double)
等と同じ強化命令).
>もっとも、符号付は、
>
> ic Rx,...
> sll Rx,24
> sra Rx,24
>
>の方が速いと思います。
#これは3命令で8バイトになります.
上位機種だとこちらの方が速いんですが,下位機種だと 24 bit シフトが遅
い(確か実測したはず)ので...とは言え,上に書いた理由でこれを使う
しかない...結局,(下位機種では;こちらのユーザーの方が速度評価が
シビアなのねん ^^;;)unsigned の方がかなり速かった,と.
>S/370 で char が符号無しなのは、文字セットが EBCDIC のためでしょ
>う。K&R の時代は「標準文字集合の要素は非負」という規定がありまし
>た。
あ,そんな規定がありましたか...何のためだろう?
>ANSI C では直接的な表現はなくなりましたが、S/370 で「文字集合が
>EDCDIC である」というためには、やはり char を符号無しとする必要
>があります。
>
># char を 16 ビットにして符号付にするという実装はアリですが、使
>#う人がいないでしょう(^^;
8 bit のデータ型が無いと I/O ドライバが書けない...(笑
>>signed
>> icm Rx,8,...
>> sra Rx,24
>#これも2命令で6バイト.
sra は RM 形式だったと思いますが、勘違いでしょうか。
>あ,ICM (insert characters under mask) は System360 には無かった
>んです(AI (add character immediate),CSD (compare and swap double)
>等と同じ強化命令).
S/360 の C コンパイラって、ありました? それで、前の記事では敢え
て S/370 としてました。(^^;;
# 370 アーキの C コンパイラを担当したこともありますが、ターゲッ
#トは汎用機ではないので、360 のことは無視してました
>>S/370 で char が符号無しなのは、文字セットが EBCDIC のためでしょ
>>う。K&R の時代は「標準文字集合の要素は非負」という規定がありまし
>>た。
>あ,そんな規定がありましたか...何のためだろう?
「'A' の値は -63 です」とか言われると困りませんか? それに、
int c;
while ((c = getchar()) >= 0) {
といった(古い)プログラムが動かなくなりますし、、、
--
片山@PFU
In article <KATE.02A...@flash.tokyo.pfu.co.jp>, KATAYAMA Yoshio wrote:
>In article <3cad2ce2$1...@binarykiller.newsgroups.com>,
> Hideki Kato <ka...@pop12.odn.ne.jp> writes:
>
>>>signed
>>> icm Rx,8,...
>>> sra Rx,24
>
>>#これも2命令で6バイト.
>
>sra は RM 形式だったと思いますが、勘違いでしょうか。
う~ん,32 ビットの命令だったかなぁ...確かにビット数指定フィール
ドが要るから...手元にマニュアルが無いので判りません (_ _).
>>あ,ICM (insert characters under mask) は System360 には無かった
>>んです(AI (add character immediate),CSD (compare and swap double)
>>等と同じ強化命令).
>
>S/360 の C コンパイラって、ありました? それで、前の記事では敢え
>て S/370 としてました。(^^;;
記憶によれば,UTS の C コンパイラはどちらでも動く(ICM を使わない)
コードを出していたと思います.また,詳しい事は知りませんが(互換機
じゃない)IBM プロパーの世界では,相当後まで前記強化命令が無いマシン
が稼動していた様な記憶があります.
>>>S/370 で char が符号無しなのは、文字セットが EBCDIC のためでしょ
>>>う。K&R の時代は「標準文字集合の要素は非負」という規定がありまし
>>>た。
>
>>あ,そんな規定がありましたか...何のためだろう?
>
>「'A' の値は -63 です」とか言われると困りませんか? それに、
これは気になりません(どうせ十進数では言わないし :-b)が,,,
> int c;
> while ((c = getchar()) >= 0) {
>
>といった(古い)プログラムが動かなくなりますし、、、
あ,これはこれは,懐かしいコードだ,,,確かに困りますねぇ :-(.
"Go Watanabe" <g...@denpa.org> wrote in message
news:a8j279$g6j$1...@sv.dsl.gr.jp...
> > と、縦書きする方法(プログラム)をよろしければ教えて下さい。
> ・最初から wchar_t の場合
> -----------------------------------------
> ・char* から一括変換して処理する場合
> -----------------------------------------
> ・char* から一文字づつ変換して処理する場合
> -----------------------------------------
>
> よーするに、いわゆる全角半角関係なく、一文字 = wchar_t 一つということ
> になります。
L”渡邊さん、ありがとうございます。
すんごく、解りやすかったです。
かつ、ドンピシャ解らなかった事の答えでした。”
L”ありがとうございます”
追記:
wchar_tは日本人が、提案して ANSI-Cに導入されたと
何かで読んだ事があるのですが、
#本当か??
私は今回初めて、wchat_t を使用したプログラムを見ました。
--
田部さんの記事<a8ik5t$1n$1...@bgsv5905.tk.mesh.ad.jp>から
> 田部です。
> 結局、CHARの型は、
> 規格では
> 2つですか?
> 3つですか?
この件は前田さんが記事<m3vgb9v...@maedapc.cc.tsukuba.ac.jp>に
引用されている通り、
文字型(the character types)には、char, signed char,
unsigned charの独立な3つの型がある
と解釈しなければならないでしょう。
そしてchar型は
(A) signed charかunsigned charのどちらかと同じ範囲、表現を持ち、
同じ様に振る舞う
にも関わらず、
(B) signed charともunsigned charともcompatibleではない
ということです。
その結果どの様なことになるかも前田さんが
記事<m3wuvp4...@maedapc.cc.tsukuba.ac.jp>で書いている通りです。
(A)よりchar型の値をsigned char型或いはunsigned char型に、何の情報
の欠落もなく変換することは出来ますが、(B)よりchar*型の値をsigned
char*型乃至unsigned char*型に変換することは保証されません。char型と
signed char型或いはunsigned char型の内部実装が同一である保証がない
からです。
(もっとも規格で保証されていないだけで、ほとんど全ての処理系でchar
型はsigned char型かunsigned char型と同じ実装を持つので、ポインタ型
を変換しても何も問題は起きない、というのが大勢の意見です。)
纏めると、規格では独立な3つの型があることになっているが、実際の処
理系の実装では、2つの独立な型があるにすぎない(ことが多い)、というこ
とです。
ポインタを変換するのは保証されず、
for (unsigned char* p = "abc"; p!='\0'; p++)
*p = (char)toupper(*p);
一文字ずつ変換しなければならない訳です。
for (char* p="abc"; p!='\0'; p++)
*p = (char)toupper((unsigned char)*p);
--
椎野 裕樹 <yu...@cds.ne.jp>
> > >あ,ICM (insert characters under mask) は System360 には無かった
> > >んです(AI (add character immediate),CSD (compare and swap double)
> > >等と同じ強化命令).
この命令の話というより、特定の OS (恐らく Unix) があるハード上で
動いた事があるかどうか関係してくるので、Subject を変えて、fj.unix
および fj.comp.arch にクロスポストします。
> >S/360 の C コンパイラって、ありました? それで、前の記事では敢え
> >て S/370 としてました。(^^;;
上記 <KATE.02A...@flash.tokyo.pfu.co.jp> での疑問に対する答として、
> 記憶によれば,UTS の C コンパイラはどちらでも動く(ICM を使わない)
これだと、少し曖昧な点が残るような気がします。つまり、S/360 の上で
UTS が動作していない限り、S/370 上の UTS 上の C コンパイラが「S/360 の
C コンパイラ」とは言えませんが、下記の記事を見る限りは、UTS が最初
に動作したのは S/370 という事のようです。
http://www.beagle-ears.com/lars/engineer/comphist/ibm360.htm
> コードを出していたと思います.また,詳しい事は知りませんが(互換機
> じゃない)IBM プロパーの世界では,相当後まで前記強化命令が無いマシン
> が稼動していた様な記憶があります.
また、「前記強化命令が無いマシン」が稼働していたとしても、その上で
C 言語が使われるかどうかは、また別の問題と思います。「メインフレーム」
を長い期間稼働させ続ける主な理由は、その上でしか動かない業務プログラム
を動作させるためである事が多いような気がしますから、古いマシンに新しい
OS を乗せて動かす事はあるとしても、それは、「IBM プロパーな OS」から選択
されそうな気がします。
つまり「最初に UTS が動作したマシンよりも古い S/360 で UTS を動作させる」
べき動機は、かなり弱そうに思います。UTS 以外の「メインフレーム」 OS 用
の C コンパイラの登場時期は、UTS に比べて相当遅いような気がするので、
「S/360 上での C コンパイラがあるか」という疑問への答は「コンパイラの
提供状況」まで含めた、OS の動作状況に強く依存するように思うのですが ...
--
橋本 剛
> (A)よりchar型の値をsigned char型或いはunsigned char型に、何の情報
>の欠落もなく変換することは出来ますが、(B)よりchar*型の値をsigned
>char*型乃至unsigned char*型に変換することは保証されません。char型と
>signed char型或いはunsigned char型の内部実装が同一である保証がない
>からです。
>(もっとも規格で保証されていないだけで、ほとんど全ての処理系でchar
>型はsigned char型かunsigned char型と同じ実装を持つので、ポインタ型
>を変換しても何も問題は起きない、というのが大勢の意見です。)
規格は、符号付き整数型とそれに対応する符号無し整数型において、
(1) 同じ境界整列(6.2.5 Types 第6段落)
(2) 非負の値は同じ内部表現となること(同 第9段落)
を処理系に要求しています。さらに、第9段落に対する脚注で、両者は、
引数、関数値、union メンバーで交換可能であることを意味していると
述べています。
union メンバーで交換可能なことから、
union { signed char sc; unsigned char uc; } x, p = &x;
signed char *ps = &p->sc; unsigned char *pu = &p->uc;
において、(unsigned char *)ps が &p->uc と等しくなる(*)処理系で
は、x.sc が非負の時は (unsigned char *)ps で参照する時の動作は保
証されます。
*このことに関して直接は規定していないようですが、ポインター同士
*の型変換は境界整列だけが問題と考えているふしがある(6.3.2.3)
*ので、保証されていると考えてもいいのではないかという気もしない
*ではありません(弱気 (^^;)
--
片山@PFU
>
>田部です。
>
>> よーするに、いわゆる全角半角関係なく、一文字 = wchar_t 一つということ
>> になります。
>
>L”渡邊さん、ありがとうございます。
> すんごく、解りやすかったです。
> かつ、ドンピシャ解らなかった事の答えでした。”
どういたしまして~
>追記:
> wchar_tは日本人が、提案して ANSI-Cに導入されたと
> 何かで読んだ事があるのですが、
> #本当か??
提案を誰がしたのかとかは知らないのですが、wchar_t 周辺の
仕様の策定にはかなり日本人が関わっているかと思います。
このあたりはたぶん熊谷さんを召喚できるとお詳しいと思うのですが……
> 私は今回初めて、wchat_t を使用したプログラムを見ました。
UNIX 方面だと、X11 の Athena Widget や Motif の国際版が wchar_t に
よる実装です。Canna も wchar_t ベースですね。商用 UNIX の国際化は
wchar_t が基本です。
一般のプログラムでは、ちょっと使ってる例は思いつかないですね。
Windows は前にもちょろっと書きましたが、Unicode 対応で組むと、
普通に wchar_t によるプラグラムになります。ただ、「wchar_t」
という型名は表だってはでてきませんし、普通 ANSI C の関数は使わずに、
WIN32 API のものを使います。一応一式ランタイム中にあります>ANSI Cの関数
wchar_t を使うと、多くの文字を扱うプログラムが比較的容易に組めるのが
特徴ですな。Java も概念的には wchar_t と同じなわけで、すげー楽です。
複雑な文字処理には使えないんだけど、そこまで要求される事例はあまり無いですし。
この辺りの疑問は尤もだと思います.私自身,この辺りの事情/歴史を全く
知らないので,上の様に(私が知っている事実のみ)書きました.また,補
足すると,ICM の様な強化命令が S/370 の全てのマシンで使えたかどうか
にも疑問をもっています.#「強化命令」という呼び方も気になる...
この話が出た当初 char はある環境での最小アドレス可能な単位で (これはい
いんですよね?), signed 或いは unsigned のどちらかが余分な情報を必要と
する場合があるのかなあ, と思っていましたが
In article <KATE.02A...@flash.tokyo.pfu.co.jp>
ka...@pfu.fujitsu.com (KATAYAMA Yoshio) writes:
> (1) 同じ境界整列(6.2.5 Types 第6段落)
[#6] For each of the signed integer types, there is a
corresponding (but different) unsigned integer type
(designated with the keyword unsigned) that uses the same
amount of storage (including sign information) and has the
same alignment requirements.
とある通り同じ量のストレージなんですよね. ううむ.
で, 「(signed/unsigned どちらか明らかでない) char をそこかしこで使うの
はよろしくない」というのは納得しかけたんですが, そうすると標準 C ライ
ブラリのほとんどが char なのは何故でしょうか.
# 歴史的経緯? …にしては restrict とか導入してるし….
--
Kazuo Fox Dohzono / doh...@hf.rim.or.jp
> >「S/360 上での C コンパイラがあるか」という疑問への答は「コンパイラの
> >提供状況」まで含めた、OS の動作状況に強く依存するように思うのですが ...
> この辺りの疑問は尤もだと思います.私自身,この辺りの事情/歴史を全く
...
google で、少し粘って探していると、OS/360 上の C compiler が "prelimary form"
ではあるが存在した事を示唆していると読めない事もない記述が見つかり
ました。^^; UTS ではなく、OS/360 の上に、動作状況の詳細は不明ですが何か
あったようです。
http://www.lysator.liu.se/c/dmr-on-histories.html
http://www.lysator.liu.se/c/chistory.ps
http://www.lysator.liu.se/c/bwk-tutor.html
#どちらも、1行触れている箇所があるだけなので、詳しくは分かりません。^^;
--
橋本 剛
In article <7b3b22aa.02040...@posting.google.com>,
t...@spp.hpc.fujitsu.co.jp (HASHIMOTO, Tsuyoshi) writes
>google で、少し粘って探していると、OS/360 上の C compiler が "prelimary form"
>ではあるが存在した事を示唆していると読めない事もない記述が見つかり
>ました。^^; UTS ではなく、OS/360 の上に、動作状況の詳細は不明ですが何か
>あったようです。
Amdhal C のことかなぁ。
M280上のは、結構速くて驚いた記憶があります。当時は、M280は、
Vax 8600 よりも速かったなぢょね。結構いろんな Unix tool を
コンパイルしていたような... Pipe が動いたかどうかは記憶にないです。
---
Shinji KONO @ Information Engineering, University of the Ryukyus,
PRESTO, Japan Science and Technology Corporation
河野真治 @ 琉球大学工学部情報工学科,
科学技術振興事業団さきがけ研究21(機能と構成)
"Junn Ohta" <oh...@src.ricoh.co.jp> wrote in message
news:a8jf3a$fi5$1...@ns.src.ricoh.co.jp...
> fj.comp.lang.cの記事<KATE.02A...@flash.tokyo.pfu.co.jp>で
> ka...@pfu.fujitsu.comさんは書きました。
> > 太田さんが主張されたいことが分からないのですが、、、
>
> けっこう微妙なんですけども...。(^^;
中略
> # それがどれくらいの手間か、というあたりは微妙かな
> # と思ったので、それは話が先に進んでから追い追い書
> # こうかな、と。:-)
片山さんが、わからないない様な、
微妙な話は、私には解りません。
・BUGだ
・遅い
・無駄だ
・メモリ食いすぎ
等の言葉を使用して説明して頂けると、
助かります。
で、ブロックといえば、こんなBUG知ってますか?
#スコープにこだわり過ぎた、若者の悲劇。
int main(int argc,char *argv[])
{
int ret ;
switch(argc) {
ret = NG ; /* ここ */
case 1: ret = OK ;
case 2: ret = OK ;
}
return ret ;
"KATAYAMA Yoshio" <ka...@pfu.fujitsu.com> wrote in message
news:KATE.02A...@flash.tokyo.pfu.co.jp...
> In article <3cac7783$1...@binarykiller.newsgroups.com>,
> Hideki Kato <ka...@pop12.odn.ne.jp> writes:
>
> >In article <m3y9g3t...@maedapc.cc.tsukuba.ac.jp>, MAEDA Atusi wrote:
> >>signedという予約語はsigned charと書くためだけに作られたものだと理解し
> >>てます。
> そう言い切ってしまうとビットフィールドの立場が無くなってしまうよ
> うな気が、、、
ちょっと話をはずしますが、
struct tag {
int a:1 ;
} R ;
int main()
{
R.a = 1 ;
printf("%s\n",R,a) ;
}
で、ビットフィールドが1BITだけで、符号付で処理する時、
R.aは0、と-1しか表現できないんで
★ギョッ★としたことありませんか?
#1を代入しても、1にならない。
――――――――――――――――――――
"tabe" wrote
<a8sbl5$rc8$1...@bgsv5905.tk.mesh.ad.jp>
about "Re: 日本人のBYTEへの異常な愛情"
on Mon, 8 Apr 2002 23:51:17 +0900
> #スコープにこだわり過ぎた、若者の悲劇。
>int main(int argc,char *argv[])
>{
> int ret ;
> switch(argc) {
> ret = NG ; /* ここ */
> case 1: ret = OK ;
> case 2: ret = OK ;
> }
> return ret ;
>}
スコープっていうか....switch を理解してないような...(笑)
{
...
} while( ret );
これをコンパイルとおるのはコンパイラのバグだって言ってるようなもんです
ね.(笑)
2002/04/09(Tue) 02:28:41
--
Word by DSS
D...@mbj.nifty.com
http://homepage2.nifty.com/DSS/
"DSS" <D...@mbj.nifty.com> wrote in message
news:20020409022...@mbj.nifty.com...
> DSS です.
>
> {
> ...
> } while( ret );
>
> これをコンパイルとおるのは
> コンパイラのバグだって言ってるようなもんです
> ね.(笑)
>
なるほDOね。
if(X) ; {
for(;;) ; {
while(1) ; {
;
}
}
}
あたりは、有名だけど、
DOの書き忘れもありか。
――――――――――――――――――――――
片山さんの記事<KATE.02A...@flash.tokyo.pfu.co.jp>から
> 規格は、符号付き整数型とそれに対応する符号無し整数型において、
>
> (1) 同じ境界整列(6.2.5 Types 第6段落)
> (2) 非負の値は同じ内部表現となること(同 第9段落)
>
> を処理系に要求しています。さらに、第9段落に対する脚注で、両者は、
> 引数、関数値、union メンバーで交換可能であることを意味していると
> 述べています。
補足ありがとうございます。結局、負の値の場合には動作が保証されな
いのですね。
> *このことに関して直接は規定していないようですが、ポインター同士
> *の型変換は境界整列だけが問題と考えているふしがある(6.3.2.3)
> *ので、保証されていると考えてもいいのではないかという気もしない
> *ではありません(弱気 (^^;)
(6.3.2.3)では
When a pointer to an object is converted to a pointer
to a character type, the result points to the lowest
addressed byte of the object. Successive increments of
the result, up to the size of the object, yield pointers
to the remaining bytes of the object.
と書かれているので、char*, signed char*, unsigned char*間の変換は
保証されていると言って良いと思います。問題はポインタを変換した後の
参照が保証されるかだと思います。
char* cp = ....;
unsigned char* ucp = cp; /* (a) OK */
unsigned char uc = *ucp; /* (b) NG? */
if (uc == (unsigned char)*cp) ; /* (c) not equal? */
--
椎野 裕樹 <yu...@cds.ne.jp>
Kazuo Fox Dohzonoさんの記事<a8rb4d$102c$1...@news2.rim.or.jp>から
> この話が出た当初 char はある環境での最小アドレス可能な単位で (これはい
> いんですよね?), signed 或いは unsigned のどちらかが余分な情報を必要と
> する場合があるのかなあ, と思っていましたが
charとsigned char/unsigned charはcompatibleではないだけで、
同じ値の範囲、表現を持ち、同様に振る舞うとされているので、結
局のところ、
> signed/unsigned char しかない (char はその片方だ)
と考えても良いと思います。compatibleではない、というのはchar
とsigned char/unsigned charが形式上異なる型だと解釈されるとい
うだけのことだと思います。つまり、
void foo(signed /* or unsigned */ char);
と
void foo(char);
は異なる関数プロトタイプを持つと云うだけの話だと解釈しています。
つまり明示的にキャストさえしてしまえば、charとsigned char/
unsigned charは同一だと考えて良いと思います。
> で, 「(signed/unsigned どちらか明らかでない) char をそこかしこで使うの
> はよろしくない」というのは納得しかけたんですが, そうすると標準 C ライ
> ブラリのほとんどが char なのは何故でしょうか.
(1) 符号付き型は符号なし方に変換できる(逆は保証されない)。
(2) 任意のオブジェクト(関数と不完全型は除く)へのポインタは
char*, signed char*, unsigned char*のいずれにも変換できる。
ので(臆測ですが)問題ないのではないでしょうか。
charからunsigned charへの変換が保証されているのでfputc()な
ども問題なく使えますし。fgetc()の返り値もEOFでなければ
unsigned charへの変換が保証されています。
問題はchar型が符号付きの場合、unsigned charからcharへの変換
がimplementation-definedである点、ポインタ値をchar*に変換する
ことは許されているが参照先をchar型のオブジェクトとして参照して
も良いのかどうか分からない点でしょうか。
逆に、char型が符号なしの場合には、(unsigned charはpure binary
notationで表わされるので)任意のポインタをchar*に変換し参照して
も問題ないでしょう。
char型が(たとえ符号付き型であっても)padding bitを持たなければ
(trap representationを持たなければ)、(不完全型ではない)任意のオ
ブジェクトをchar型オブジェクトの列として参照しても良いことにな
りそうです。(char型が符号なしの場合には、これを満たします。)
--
椎野 裕樹 <yu...@cds.ne.jp>
<a8sbl5$rc8$1...@bgsv5905.tk.mesh.ad.jp>の記事において
ta...@mug.biglobe.ne.jpさんは書きました。
> 片山さんが、わからないない様な、
> 微妙な話は、私には解りません。
> ・BUGだ
> ・遅い
> ・無駄だ
> ・メモリ食いすぎ
> 等の言葉を使用して説明して頂けると、
> 助かります。
メモリ(スタック)消費量の見積もりが微妙で難しいってんじゃないの?
ここでのコンテキストは「見積もり」なんでしょ?
# まぁ、確かに最初の大田さんの記事では、ちと微妙すぎてわからんか
# ったけれど、フォローの記事をじっくり読めば分かるかと。
> で、ブロックといえば、こんなBUG知ってますか?
> #スコープにこだわり過ぎた、若者の悲劇。
> int main(int argc,char *argv[])
> {
> int ret ;
> switch(argc) {
> ret = NG ; /* ここ */
> case 1: ret = OK ;
> case 2: ret = OK ;
> }
> return ret ;
> }
スコープにこだわりすぎたというより、単に理解していないだけでは…
(^^;;;
--
成田 隆興 @ エー・アイ・ソフト株式会社ソリューシュン開発部
E-mail tak...@aisoft.co.jp
『十分間で決断し、短い理由を添えよ。』
<a8tm2n$2075$1...@nwall1.odn.ne.jp>の記事において
tak...@aisoft.co.jpさんは書きました。
> # まぁ、確かに最初の大田さんの記事では、ちと微妙すぎてわからんか
ごめんなさい。大田さん(誤り)->太田さんでした。(^^;
> > で、ブロックといえば、こんなBUG知ってますか?
で話は見積もりから離れて、Common LISP のように
{
int foo;
char bar[256];
void gachon() {
:
}
}
とかあると面白いかも、とか考えたことはあったり。この方が、
void gachon() {
static int foo;
static char bar[256];
:
}
やファイルスコープも当て込んでの
static int foo;
static char bar[256];
void gachon() {
:
}
より直感的に初心者には分かりやすいかもとか。
# 単なる思いつきにしかすぎないのだけれど。
わかりにくくてすみません。(^^;
田部さんが例に挙げられた3つのbufは、たしかに同時に
はアクセスされないので別々に領域を確保するのは無駄
だけど、かといって占有メモリーを減らそうと思ったら
遅くなるかもしれないよ、というのが本来の意図です。
田部さんが何を考えているのかよくわからなかったので
すが、たとえば関数の入口でそれらのbufを同じ場所に
確保して共用するとしたら、デバッガーでwatchしたり
するときに困りますよね。かといってブロックの入口で
ちゃんと確保・解放するとしたら遅くなる。
元の例では処理系はおそらく3つのbufを関数の入口で確
保しているのでしょうけど、田部さんがそれをどう理解
していて、どうあってほしいと思っているのかもう少し
詳しく聞きたかったのであのような書きかたをしたわけ
です。
>> *このことに関して直接は規定していないようですが、ポインター同士
>> *の型変換は境界整列だけが問題と考えているふしがある(6.3.2.3)
>> *ので、保証されていると考えてもいいのではないかという気もしない
>> *ではありません(弱気 (^^;)
> (6.3.2.3)では
> When a pointer to an object is converted to a pointer
> to a character type, the result points to the lowest
> addressed byte of the object. Successive increments of
> the result, up to the size of the object, yield pointers
> to the remaining bytes of the object.
>と書かれているので、char*, signed char*, unsigned char*間の変換は
>保証されていると言って良いと思います。
はい、そうでした。(_ _;
>問題はポインタを変換した後の
>参照が保証されるかだと思います。
> char* cp = ....;
> unsigned char* ucp = cp; /* (a) OK */
> unsigned char uc = *ucp; /* (b) NG? */
これは、6.2.6.1 の 第4段落で保証されています。
> if (uc == (unsigned char)*cp) ; /* (c) not equal? */
これは、not equal となる場合が考えられます。char が符号付きで、
符号付き整数が 1の補数表現や絶対値表現において、*cp が -0 の場合
です。
# trap representation も考えたのですが、第5段落では文字型を除い
#ているので、文字型は trap representation を持てないと解釈して
#います
# signed char 型ならパディングビットを持てますから、-0 以外の場
#合も考えられますが、現実的ではないでしょう(^^;
--
片山@PFU
>S/370 で char が符号無しなのは、文字セットが EBCDIC のためでしょ
>う。K&R の時代は「標準文字集合の要素は非負」という規定がありまし
>た。
>ANSI C では直接的な表現はなくなりましたが、S/370 で「文字集合が
>EDCDIC である」というためには、やはり char を符号無しとする必要
>があります。
無くなっていませんでした。(_ _;
6.2.5 Types
3 An object declared as type char is large enough to store
any member of the basic execution character set. If a
member of the required source character character set
enumerated in 5.2.1 is stored in a char object, its value is
guaranteed to be positive.
#このところボケまくってる、、、
--
片山@PFU
>田部さんが何を考えているのかよくわからなかったので
>すが、たとえば関数の入口でそれらのbufを同じ場所に
>確保して共用するとしたら、デバッガーでwatchしたり
>するときに困りますよね。
そういうことだったのですか。しかし、配列でなく単純変数の場合は、
そういうことをしてますが、それは困らないのでしょうか。
>かといってブロックの入口で
>ちゃんと確保・解放するとしたら遅くなる。
ちゃんと確保・解放しても同じアドレスになる場合は困らないのでしょ
うか。
#確保・解放のついでに、デバッガーに通知する命令も埋め込んでおく?
--
片山@PFU
ふつうビットフィールドにはビットパターンしか格納し
ないので、誰も★ギョッ★としたりはしないと思うので
すが、どうでしょう?
もちろん、数値でないものを数値として扱おうとしたら
さまざまな場面で★ギョッ★とする羽目になるのは当然
なんですけど。
なんつうか、田部さんの挙げられる例ってどれもこれも
「思い込み先行型」なんですよね。言語仕様の本質をお
さえていればつまずいたりするはずのないところでつま
ずく例だらけというか...。
田部さんはご自分のところの若者のスキルを嘆いてらっ
しゃるけど、田部さんと同じような環境、同じような方
針で教育を受けているのなら、そういう状況になるのは
無理もないのではないか、という印象です。
「そういうこと」というのは「関数の入口で同じアドレ
スに割り振って共用する」ということですか?
単純変数でそれをしているなら配列でももちろん問題な
いでしょうね。単純変数についてそうする処理系だった
ら配列でも同じ方針をとると思います。
> #確保・解放のついでに、デバッガーに通知する命令も埋め込んでおく?
watchしたければそうするしかないのではないかと思う
のですが。
>> そういうことだったのですか。しかし、配列でなく単純変数の場合は、
>> そういうことをしてますが、それは困らないのでしょうか。
>「そういうこと」というのは「関数の入口で同じアドレ
>スに割り振って共用する」ということですか?
はい。
>単純変数でそれをしているなら配列でももちろん問題な
>いでしょうね。単純変数についてそうする処理系だった
>ら配列でも同じ方針をとると思います。
gcc が「単純変数は関数の入口で同じアドレスに割り振って共用するが、
配列はそうしない」処理系の一つです。Sun のコンパイラの幾つかを見
てみましたが、同様でした。
#だからどうしたというのではなく、そんな処理系もあるという報告です
--
片山@PFU
こーいうのもありますね。
while ( loop_flag ) {
...
} while ( loop_flag2 );
--
田中一嘉
mailto:den...@lycos.ne.jp
"TANAKA Kazuyoshi" <den...@lycos.ne.jp> wrote in message news:a8uln0>
> こーいうのもありますね。
> while ( loop_flag ) {
> ...
> } while ( loop_flag2 );
こういうのもある。
while ( Roop_flag ) {
嘘だと思ったら、
即
%grep -i roop *.[ch]
> メモリ(スタック)消費量の見積もりが微妙で難しいってんじゃないの?
> ここでのコンテキストは「見積もり」なんでしょ?
はい。そうです。
>
> # まぁ、確かに最初の大田さんの記事では、ちと微妙すぎてわからんか
> # ったけれど、フォローの記事をじっくり読めば分かるかと。
うう。
> > #スコープにこだわり過ぎた、若者の悲劇。
> > int main(int argc,char *argv[])
> > {
> > int ret ;
> > switch(argc) {
> > ret = NG ; /* ここ */
> > case 1: ret = OK ;
> > case 2: ret = OK ;
> > }
> > return ret ;
> > }
>
> スコープにこだわりすぎたというより、単に理解していないだけでは…
> (^^;;;
「スコープを限定するのは、良い事だ」と習った若者が、
if(X) {
int ret = NG ;
~長い処理~
return ret ;
}
が、巧くいったので、これの
SWITCHバージョンを「考えついちゃった」様です。
--
> わかりにくくてすみません。(^^;
同じく、済みません。
> 田部さんが例に挙げられた3つのbufは、たしかに同時に
> はアクセスされないので別々に領域を確保するのは無駄
> だけど、かといって占有メモリーを減らそうと思ったら
> 遅くなるかもしれないよ、というのが本来の意図です。
私が試したコンパイラは、
EWS4800のMIPS用セルフコンパイラです。
EWS4800のgccで見ると3つのBUFは共用されていました。
セルフコンパイラが、3つのBUFを別々にとるのは
パイプラインだの、キャッシュだのRISC特有の処理を考慮した
コードを生成してるのかな~と思いました。
真実は不明。
>
> 田部さんが何を考えているのかよくわからなかったので
> すが、たとえば関数の入口でそれらのbufを同じ場所に
コンパイラが、いろいろやるので、
スタック見積もりは難しい。
と、言いたかっただけです。
> 確保して共用するとしたら、デバッガーでwatchしたり
> するときに困りますよね。かといってブロックの入口で
> ちゃんと確保・解放するとしたら遅くなる。
>
> 元の例では処理系はおそらく3つのbufを関数の入口で確
> 保しているのでしょうけど、田部さんがそれをどう理解
> していて、どうあってほしいと思っているのかもう少し
> 詳しく聞きたかったのであのような書きかたをしたわけ
> です。
・関数の入り口で、3つのbuf分のスタックを確保して、
出口で開放していると理解しています。
予想では、共有していると思ったのですが、
EWS4800 MIPSセルフコンパイラでは予想が外れた。
gccでは予想通りとなりました。
#故にスタックの消費量の見積もりは一筋縄では行かない。
・どうあって欲しいかと言うと、私はUNIX屋なので、
早ければそれでいいや。
です。
#PROFの結果を見ると、
分けた時と、
分けない時とで
クロック数はぴったり同じでした。
―――――――――――――――――――――――
"Junn Ohta" <oh...@src.ricoh.co.jp> wrote in message
news:a8u18q$79b$1...@ns.src.ricoh.co.jp...
> fj.comp.lang.cの記事<a8sbl7$rc8$2...@bgsv5905.tk.mesh.ad.jp>で
> ta...@mug.biglobe.ne.jpさんは書きました。
> > ビットフィールドが1BITだけで、符号付で処理する時、
> > R.aは0、と-1しか表現できないんで
> > ★ギョッ★としたことありませんか?
>
> ふつうビットフィールドにはビットパターンしか格納し
> ないので、誰も★ギョッ★としたりはしないと思うので
> すが、どうでしょう?
struct tag {
int a:1 ;
} R ;
int main()
{
R.a = 1 ;
if(R.a == 1) {
;
} else {
printf("こっちに来たら★ギョッ★としませんか?”);
}
}
#ビットフィールドは、コンパイラ依存のところが多々あるので、
#コンパイラを変えたら、
#「省略時解釈が、符号付から、符号無しへ変わった」
#って、結構あると思うのですが。
> もちろん、数値でないものを数値として扱おうとしたら
> さまざまな場面で★ギョッ★とする羽目になるのは当然
> なんですけど。
私の様なトラディショナルCプログラマは、
ビットフィールドは符号無しと思い込んでいる場合が
少なからずあると思うのですが、
皆さんどうでしょうか?
> なんつうか、田部さんの挙げられる例ってどれもこれも
> 「思い込み先行型」なんですよね。言語仕様の本質をお
> さえていればつまずいたりするはずのないところでつま
> ずく例だらけというか...。
私は、
http://rec.ncos.co.jp/
こんなの、作っているので、
普通の人の百倍くらい、変なコードを見てきました。
で、太田さんの言う様に
変な「思い込み」で凄い苦労しているのを
多々見てます。
さらに別の言い方をすると、
変なコーディングをしない人はいません。
> 田部さんはご自分のところの若者のスキルを嘆いてらっ
> しゃるけど、
嘆いてはいません。
又やるなよと「ここで」いっていますが。
> 田部さんと同じような環境、同じような方
> 針で教育を受けているのなら、そういう状況になるのは
> 無理もないのではないか、という印象です。
質問1:
ヘッダファイルにstatic が無かった
太田さんの所で、出るBUGはどんなBUGでしょうか?
うちで「も」出たBUGは
http://rec.ncos.co.jp/
こんなのですが、
抽象表現でもOKですので、
事例を教えて下さい。
興味津津。
> --
> 太田純(Junn Ohta) (株)リコー/新横浜事業所
> oh...@sdg.mdd.ricoh.co.jp
--
そうでしたか。だとするとこの件での私の認識は間違っ
ていたようです。失礼しました。田部さんにも悪いこと
しちゃったな...。
> 田部です。
> こういうのもある。
>
> while ( Roop_flag ) {
文字列リテラルと注釈以外でいわゆる全角文字を使ったら、コンパイラは
エラーを吐いて止まるから、問題ないんじゃないかな?
> 嘘だと思ったら、
> 即
> %grep -i roop *.[ch]
"-i" オプションでいわゆる全角文字/半角文字の lower case, upper case
を無視してくれるような grep があるんですか?
たまに欲しいと思うことがあるけど、たいていはうっとうしそうな気がする。
---------------------------------------------------------------------
tesi...@mtf.biglobe.ne.jp
言語仕様の無理解によるミスは田部さんのところより少
ないようですが、ロジックのミスはたくさん出ますよ。
場面を尽くしていないので特定の条件のときにおかしな
パスを通ってしまう、あるいは特定の条件のときに通る
べきコードが用意されていない、などですね。
今回の件は私の勇み足でした。申し訳ない...。
> コンパイラが、いろいろやるので、
> スタック見積もりは難しい。
> と、言いたかっただけです。
とはいえ、スタックの使用量をある程度精密に見積もり
たかったら、そうしやすいようにプログラムを書くこと
はむずかしくないですよね。それでプログラムが読みに
くくなるほどのことでもないですし。
# こういうのを「亀レス」とかいうんだろうな。遅くなって
# 申し訳ないです。
On 02 Apr 2002 03:32:33 +0900, in
<m3u1qvu...@maedapc.cc.tsukuba.ac.jp>,
MAEDA Atusi <ma...@cc.tsukuba.ac.jp> wrote:
>最近のライブラリ関数(マクロ)使っても大小比較いりますかね?
申し訳ないんですが、その最近のライブラリ関数ってのを知らないです。
教えていただけると、とってもうれしいです。<(_ _)>一旦Unicodeに
変換して…っていう話なんでしょうか?もし教えていただいて、機会が
あればそっちで書き直すでしょう。それはさておき。
私が出会った事例ですが、Macintoshの環境だと○に数字の入った文字の
字体と文字コードが、表示するフォントによって一部ずれている(Osaka
フォントで○の中に1を表示するコードを細明朝で表示すると同じ字体に
ならない)から、それを調整する場合、
if (0xfc00 <= c && c <= 0xfd00 …)
とか書きたくなりませんか?(即値は適当)で、この時に c に符号拡張が
起こるとこの条件判断をすり抜けちゃうんじゃないかと。
で、ここまで書いて気がついたんですけど、c に対して Windows の場合
MAKEWORD とかちゃんと使っていれば、問題ないはずなんですよね。他の
環境でも同じようなマクロを書けばいいし。まあちゃんと使ってない
ソースもひっくるめてメンテナンス/開発している(自分でI/Fも書くなら
char *で回すだろうというのは前の記事で書きました)んで一筋縄じゃ行
かないけど、それこそ特殊というのは納得です。
>i == -1が間違いなのか間違いじゃないのか良く分からないんですけど、本当
>に間違いじゃないかも...(本当にa[-1]を参照するのが正しかったりして)。
a[-1]をアクセスするのは(前の記事にも書きましたが)可能性はあります。
ただしインデックス値を unsigned の型にすることで、「この配列に
マイナスのインデックス値を取ることはプログラマの意図したところではなく、
そんなことが起こればバグだ」とメンテナンスしている人に意図が伝わるかな
という感じでした。
>ふーむ。こういうときにハンガリアンなんですかねえ。本当は型じゃなくて
>API の慣習なんだけど。
これは私を含めての周りの開発がほとんどWindowsべったりなんで
それに合わせているのはあります。
ついでにいえば…
>文字コード依存のコードがどうしても要っても、一回ライブラリ書いて閉じ込
>めてしまえば普段のコードには出てこない気がしますが。
アプリケーションを作った最初は、SJIS-JIS変換だけで済んでいたのが、
仕様を拡張したらUNICODEが入ってきたり、移植をしたらMacintoshのSJISは
また違っていたり…とか、ターゲットのOSでは文字コードを変換する(ひらがな→
カタカナとか)ライブラリが無かったとか…。
なんかその手のライブラリ作成に時間をかけたような記憶はあります。こんなの、
一回書いてしまえば、ほとんどどこでも通用するんですけど、「Windowsではこんな
ライブラリがあるからそれを使った」と言われると、移植する方は「なければ作る」
しかないわけで、頻度は高くないけれど、そういうライブラリを書く羽目に陥ること
はあります。
# 正しい仕様を実装するのではなく、オリジナルと同じ動作をするコード
# が求められる…。
## そういう自分がダメダメじゃんというのはおいといて。
---------
山村 隆志 「debugは3歩後退、2歩前進、いつまでたっても終らない」
e-mail : vy...@janis.or.jp
WWW page : http://www.janis.or.jp/users/vyama/
<tesi...@mtf.biglobe.ne.jp> wrote in message
news:a8v3na$q5d$1...@bgsv5906.tk.mesh.ad.jp...
> "tabe" <ta...@mug.biglobe.ne.jp> writes:
> >
> > while ( Roop_flag ) {
>
> 文字列リテラルと注釈以外でいわゆる全角文字を使ったら、コンパイラは
> エラーを吐いて止まるから、問題ないんじゃないかな?
いえ、あのここでは、
エル(Loop)と書くべき所で、
アール(Roop)と書いているのが、ミソでして。。。。
このRoopが見つかると深刻だ。
一度もレビューを受けた事が無い、プログラマが作った。
一度もレビューを受けた事が無い、プログラムの可能性がある。
--
"tesi...@mtf.biglobe.ne.jp" wrote:
> > 田部です。
> > こういうのもある。
> >
> > while ( Roop_flag ) {
>
> 文字列リテラルと注釈以外でいわゆる全角文字を使ったら、コンパイラは
> エラーを吐いて止まるから、問題ないんじゃないかな?
田部さんが言いたいのは、本来loopと書くところをroopと書いていたりする、
読むものを混乱させるような誤植変数名なんかありませんか?
という意味だと思います。
(上ではあくまで強調の意味で全角文字を使っているだけで、
grepの例ではちゃんと半角になっているのはそのためかと)
他にも、
idle vs idolとか、route vs root等々、考えると色々出てきます。
(最近見つけた誤植では(変数ではないが)Hoolってのがあった。
あと、意味違いっていう意味では「内臓ハードディスク」等が
あちこちのホームページに(笑))
(かつで、某社では、変数名にガ○ダムの登場キャラ名使ったのが
あったらしい(--#)
違うかな?
>> while ( Roop_flag ) {
>文字列リテラルと注釈以外でいわゆる全角文字を使ったら、コンパイラは
>エラーを吐いて止まるから、問題ないんじゃないかな?
ところが、C99 では識別子に“other implementation-defined
characters”が使えるようになりましたから、Roop_flag を識別子と
扱う規格合致処理系があるかもしれません。
universal-chrarcter-name を使って \uff32oop_flag と書きたいとこ
ろですが、ff32 は Annex D に含まれませんので、未定義動作になって
しまいます。
# \u6f22\u5b57\u8b58\u5225\u5b50 と書けても嬉しくないか、、、
--
片山@PFU
e1.cに「C言語仕様で不定!」というタイトルで
buf[i++] = i++ ; /*←BUG !! */
という例が出ていますが、そのすぐ下でリンクされてい
るC FAQにも説明があるとおり、規格では「不定」では
なくて「未定義」ですよね。「どちらのi++が先に実行
されるかわからない」だけでなく、そもそも2つのi++が
いずれかの順番で実行されることすら期待してはいけな
いということ。ここは書きなおされてはいかが?
この手の潜在バグでは、うちでも
putchar(*p++);
という例を見たことがあります。putchar()マクロは引
数を1回しか評価しないことが保証されているわけでは
ないので、複数回のインクリメントが行われる可能性が
あるわけです。(でも最近の実装ではたいてい1回しか評
価しないようになっているかな。)
> putchar(*p++);
>
> という例を見たことがあります。putchar()マクロは引
> 数を1回しか評価しないことが保証されているわけでは
> ない
保証されていると思います.
7.1.4 Use of library functions
[#1] ... Any invocation of a library function that is
implemented as a macro shall expand to code that evaluates each
of its arguments exactly once, fully protected by parentheses
where necessary, so it is generally safe to use arbitrary
expressions as arguments.
太田さんはおそらく putc 等における stream の扱いと混同されているのでは.
7.19.7.8 The putc function
#include <stdio.h>
int putc(int c, FILE *stream);
[#2] The putc function is equivalent to fputc, except that
if it is implemented as a macro, it may evaluate stream more
than once, so that argument should never be an expression
with side effects.
# 初期の glibc のマクロは c の方を二度以上評価していた.
--
Kazuo Fox Dohzono / doh...@hf.rim.or.jp
あ、ANSI以降は保証されるようになったんでしたっけ?
> 太田さんはおそらく putc 等における stream の扱いと混同されているのでは.
いや、混同していたわけではないです。
> > 保証されていると思います.
>
> あ、ANSI以降は保証されるようになったんでしたっけ?
ANSI でも保証されていた (その頃そういう話を知った) と思いますが, それ
以前はわかりません (_ _
# C99 にざっと目を通した限りでは, getc, putc, getwc, putwc の stream
# 以外に二度以上評価され得るものはないようです.