C言語なら俺に聞け 149
■ このスレッドは過去ログ倉庫に格納されています
負の数を識別できません。
signed int DATA = -128 (0xFF80。int は16ビット)
if (DATA > 0)
{式1}
else
{式2}
なぜか式1 が実行されます。(DATA > 0) は偽ではないのでしょうか。 問題のコードから症状が出るままどんどん削ってって最小単位がそのコード?
https://ideone.com/xcDRkc
実は右辺がcharの変数で 中身が 0x80 なんだけど
符号拡張の過程で char を unsigned char として 0x0080 と拡張したり
(処理系依存だっけか? リテラルだけだっけ?)
そういう話ではない? >>103,104
右辺の0は定数です。
変数DATA の値はPRINT文で16進表示したものです(0xFF80)。
引用先のページは、残念ながら理解できませんでした。
申し遅れましたが処理系は組み込み用16ビットマイコン用GCC です。
処理系に依って前述のような動作になることはありえますか? 右辺云々は 初期化の右辺の話だけども、そこが本質じゃなさそうね
sizeof(int) = 2 かつ printf("%x", DATA) が ff80 と表示される系で
if (DATA > 0) が成立しないとな
ごめんワカラン 最小の全ソースを見せて。
この手の場合、自分では正しいと思ってるとこに思わぬポカミスが入ってることがまれによくある。 >>106,107
すいません。ご察しのとおり、変数DATA に初期値を代入しているわけではありません。
このif 文が評価される直前のDATA 値が-128 という事で、初期値を代入したように書きました。
今日はこの件で非常に疲れたので、ソースの提示は少し時間を下さい。ありがとうございます。 >>107
元コードをそのまま横断的に眺めてるとわからないけど
症状が残るまま、余計な箇所をがんがん削っていって簡単化していくと見つかることがあるよね
a[i++] = i; のような副作用完了点内での複数回の参照とかはどうしようもないけどw 値自体は型情報を含んでないという点は押さえないとあかんが、そういう問題でもないか。
妙なtypedefしてたりしてね。 アセンブリコード読んで見るとか
割り込みでレジスタ確認とかすれば
cで見てると気づかないことが見えてくるかも printf("check : sizeof %d: DATA = %d\n",sizeof(DATA),DATA);
if((signed int)DATA > (signed int)0)
とかやって一つ一つ動作確認してみるとか。
よくわからん動作不良起こした時は配列変数がスタックサイズ超えてたとか
16Bit環境なら32kb/64kb超えたとかが原因だったことあるけど。 >>108
そもそもその環境で>>102のコードを実行したらどうなるのさ? >>102
本当に DATA の型は signed int か?
良く見たら unsigned int ってことはないか? >>102
16進リテラルが16bitで収まらないからunsigned intで解釈された。(c99)
そんでintに暗黙キャストされたときに最上位bitが落ちたと思われ >>108
> 今日はこの件で非常に疲れたので、ソースの提示は少し時間を下さい。ありがとうございます。
正しい。疲れたら休め。結果的にその方が早い。
君も分かっていると思うが、まともなコンパイラ(実績のあるコンパイラ)なら、そんなところにバグはない。
ほぼ間違いなく君の勘違いだ。
それは根詰めて見てても気づかないが、一旦忘れて見直したらあっさり見つかる、ということもよくある。
残業してグダグダやるよりも、早く帰って早く寝て、次の日に早めに出社した方が捗る。
おそらくあっさり解決すると思うぜ。 リテラルの大小によって、型が変わるとか、滅茶苦茶な文法だろ
コンパイルエラーにしろよ。
気づかねえ ソースの見栄えで桁あわせにゼロパディングしたら 8進数になっててうぁぁぁ マジックナンバーあかんとか言ってもさあ、マクロで隠したせいで生じたバグも経験的にはかなり多いんだよね。
値のリテラル即悪みたいなのもどうかと思うね。 >>117
型は変わらないし、普通は警告が出るはず。
いずれにしても、C言語はお前みたいな馬鹿向けには出来てない。
>>115
unsigned int から int へのキャストは普通はそのままで、飽和処理なんてしないだろ。
仕様なのか処理系依存なのかは知らんが。 >>119
何をリテラルにして良いか判断出来ないのは君(または周り)の問題だろ。
独り言ではなく、問題提起〜議論起動する気があるのなら、「俺なりの基準」でも言えよ。 >>120
>型は変わらないし
つ6.4.4.1
>普通はそのまま
intの最大値を超えているのにどうやって表現する気だ >>122
> intの最大値を超えているのにどうやって表現する気だ
ならお前はdoubleの最大値を超えている場合はどうするんだ?
お前みたいな馬鹿が使うようには出来てないんだよ。 30年ぐらい前にZ80のマイコンボード用に作ったプログラムでそれにハマった覚えがある。 すぐ16進で書きたがるのもどうかと思うわ。
intに-1でなくて0xffffffff入れてるのとか意図が掴みかねる。
そもそもunsignedがあるのが良くないんだな。javaは正しかった。 70年代初期に何が良いか何が悪いか何が正解かが分かるの?
それに磁気コアメモリが4096ビットの時代だよ >>125-127
リテラル中に 8 や 9 が入ってれば文法エラーで止まるので判明するけど
入ってないとそのまま通っちゃうし、特に警告の対象になるようなもんでもないしでやっかいよね >>130
今時8進表記なんて使うことはほぼないと思うから使ってたら警告してもいいくらい >>109-116
皆さんご助言ありがとうございます。おかげさまで一応不具合は解消できました。
以下問題の箇所です。
signed int MAX, WIDTH, TMP, SHIFT;
float COEF;
COEF = MAX / WIDTH; //浮動小数点演算になると思っていた
// 1 = 128 / 128
TMP = SHIFT * COEF;
// -128 = -128 * 1
if (TMP > 0)
{式1} //TMP= -128 なのに、式1が実行される。
else
{式2}
だったのを
COEF = ((float)MAX / WIDTH);
に修正すると、式2 も実行されるようになりました。他に変更したところはありません。
今まで何故(-128 > 0)が真だったのかは不明です... >>132
本当に if の直前で TMP がマイナスだったのかが怪しい。
それと気になるのはやはり型が本当にその通りなのかだな。 本当に変数の型は signed なのか?
実際に 式2 に通って欲しいのに 式1 へ流れた MAX, WIDTH, SHIFT の値 をメモって
再現する最小セットのコード作って何が起きてるのか把握しとかないと、また同じことやらかすかもよ
signed int TMP;
signed int MAX = <リテラル>;
signed int WIDTH = <リテラル>;
signed int SHIFT = <リテラル>;
float COEF;
COEF = MAX / WIDTH;
TMP = SHIFT * COEF;
printf("1:%d\n", TMP);
if (TMP > 0) { printf("1:式1\n"); } else { printf("1:式2\n"); }
COEF = ((float)MAX / WIDTH);
TMP = SHIFT * COEF;
printf("2:%d\n", TMP);
if (TMP > 0) { printf("2:式1\n"); } else { printf("2:式2\n"); } >>132
皆が指摘しているように、それだけでは無いと思うがな。
おそらく君が出してきたソースにも色々間違いがあるんだろうけど。
ソース見る限りズブの初心者のようだが、問題点を理解しているか?
まず用語がおかしいので先にこれを修正しておくが、普通は
float scale = width / max; だ。shiftは足すもの、scaleが掛けるもの。coeffは係数=無次元数だろ。
読んだときに違和感がないようにしろというのはアプリケーションハンガリアンの思想だが、
これを採用するかはともかくとして、思想自体は当たってる。
そして通常は max で割る。(ただしこれについては、意図的に逆数にすることもあるが)
あと変数を全部大文字にするのはマジで止めろ。そんなことしてる奴は居ないだろ。
それで、君の「キャスト忘れ」についてはscaleが0に張り付くなり、整数の階段状になるので、
「動作を見た瞬間にどこがバグっているか分かる」タイプのバグになる。
追跡するにも苦労しないし、そもそも追跡の必要すらない。
当然、疲れもしない。マジで10分で修正して、てへぺろ、だ。
だからそのバグを取るのに手こずること自体がおかしい。
そしてその遠因になっているのはその意味不明なネーミングだ。
まずはそこからだと思うぜ。
(-128 > 0)が真になることはないので、確実に君が何か勘違いしている。
先生/先輩/上司その他、見てもらえる人がいるのなら、
君のソースのその酷さも含めて見てもらった方がいい。
そういう人がいなくて君が一人でマイコンを動かそうとしてるのなら、今の君では無理だと思うぜ。
Python馬鹿なら、最近はPythonが動くマイコンもあると聞くので、環境を変えた方がいい。
マイコン環境のCは、色々と貧弱な分、PC環境のCより難しい。
今の君ではPC環境のCでも無理がある。
状況聞く限り、俺は>>135の予想が正しいと思う。 ズブの素人が来てよかったね
嬉しそう
生きがいみたいなもんだな 何が起きていたのか本人は追求する気はないみたいなんで
話はこれ以上進まないだろう
>>137
で、それがお前の生きがいなわけだ
なんだかな 低学歴知恵遅れが
低学歴知恵遅れ丸だしなレスして
イキイキしてる >>137,138
まあお前らは上達しないと思うぜ。
最近お前らみたいな奴も増えたが。
上達出来るかは結局、自分で深みに突っ込んで行けるかにかかってる。
俺の指摘が間違っている、というのならともかく、
気に入らない指摘は無視すればいい、というスタンスなお前らはプログラマは無理だ。
諦めて他の職を探せ。
132は努力しているようだが、方向を間違っている。
それはお前らにも見えてることだろ。放置するのもまた悪だと思うぜ。
巻き込まれるのが怖くて見て見ぬふりをして、結果、
陰湿ないじめが横行してたゆとりなんてその程度だと思うが。
勿論132も追求した方がいいとは思うが、正直、そのレベルじゃない。
PC環境のCでGUIのIDEを使ってまずCを覚えるか、
既にプログラミング出来るのならその言語、調べたところRubyが動くのもあるようだから、そっちから行った方がいい。
Cも初めて+マイコンも初めて、では、確実にはまる。 こんな低学歴知恵遅れ丸出しな長文レスばっかりで埋め尽くされると
まともなヤツは近づかなくなるわ
やはり自覚がない >なんだこれ?引数 void って初めて見たぞ。文法的にありなのかこれ?
まーたこのゴミが登場したのか
もう出てけよ
余りにもゴミだからこのスレにはいらねーよ この議論に参加してくださった皆さん
>>136 さんの指摘は初心者の私には大変有難いものでした。
ただ、いくつか反論したい部分もあります。私はハード屋で、ハードウェア言語で使われる変数(フリップ・フロップ)の動作遷移を意識した変数名にした方が私には分かり易いのです。
変数を全て大文字にしているのは単純に昔からの癖です。命令文 = 小文字、引数,変数 = 大文字 と決めています。
「キャスト忘れ」についてですが、異常動作に即気付けるか否かはint 変数をキャストしないと
0,1,2・・・などの整数にしかならないことを知らなければなかなか気付けない事ではないでしょうか。
Cの参考書は持っていますが、浮動小数点演算に関連する情報が離散していて、この事象が起こりうるという説明を見出すことが出来ませんでした。
>>134 さんが提示されたテスト・プログラムは余裕が出来た時に実行してみるつもりです。現在このプロジェクトはほぼ完成しており、細かな調整を残すのみです。ありがとうございます。 >>144
まずは問題解決とプロジェクト完了おめでとうございます。
分かってると思いますが、ここは教えたがりな人、説教したい人、煽りたい人がマウントとり合うだけのスレなので、あまり細かいことは気にせず自分に有用な情報だけ吸収してくださいな。 すごいゲスパーだけど
式1 式2 が実際にはハードからの電圧出力やリレーのON/OFFで
オシレータか分周器書いててオシロで当たったら、どうもデューティーがおかしい
ってなったのかな Cは型を意識しないとどうしようもないという所はあるよね。
なので、そもそも型変換が入る余地のない、キャストに頼らないコードを書くという強い意志を持つのが大事なんじゃろうと思う。 >>141
おまえの指摘が間違っているかどうか以前に
おまえは何を指摘したんだ?
たとえば「10分」という物理量はどういう計算で出てきた値だ?
テキトーすぎて相手するに値しないんだが >>143
> ワッチョイ ff12
回答無し
だからゆとりは駄目なんだよ
>>149
> ワッチョイ 3308
同上 >>144
> ハードウェア言語で使われる変数(フリップ・フロップ)の動作遷移を意識した変数名にした方が私には分かり易いのです。
他文書と同期したいのならコメントに残せ。
ソフトウェアはソフトウェアだけで評価出来ないと管理上問題だ。(大体において同期が取れずに意味不明になる)
そもそもその部分、ハード叩いている感じでもないし。
それ以前にFFの状態遷移でSHIFTも無いと思うが。
> 命令文 = 小文字、引数,変数 = 大文字 と決めています。
これはマジで今すぐ直せ。
大文字にするのは目立たせる為であって、RAMが64バイトしかないような環境ならさておき、
今時ただの変数なんて目立ったら余計に邪魔になるだけ。今時白黒端末もないから、普通は、
命令文(キーワード)=青(色付き)、引数/変数=黒(色無し)、マクロ=全大文字、と大体相場が決まっている。
(そもそもverilogにも大文字文化はない。VHDLには多少有った気もするが…)
> Cの参考書
Cに限らず、プログラミング全般で、入門書/参考書はゴミだ。理由は筆者自身がゴミだから。
海外の参考書は一部達人が書いている物があって、それは参考になるらしいが、俺はよくは知らん。
(ただこれも、昔からプログラミングをやっているのなら常識のはずだが)
> この事象が起こりうるという説明
int/int は端数切り捨てで商のみが返る、というのはCの仕様だ。
> 変数を全て大文字にしているのは単純に昔からの癖です。
言っちゃ悪いが、君は「昔から」というほどプログラミングをやってないはずだ。
昔からやってるなら、マイコンで割り算やfloatを使うこと自体が無いし、
Cの割り算の仕様を知らないこともない。
そしてそのソフトウェアの完成度で良しと出来ること自体が(普通のプログラマからすると)キチガイじみてる。
確実に事故るぞ。 >>144(続き)
ただしあまり反発もないところを見ると、ただのゆとり(若者)でもないらしい。
仮に全てを満足出来るプロフィールを定義すると以下となるが、合ってるのか?
・全て大文字とはCOBOL/FORTRAN/BASIC/アセンブラの世界。つまりC以前からであり、プログラミング歴自体は長い。
・Cの基本的仕様を知らない=Cは普段使いではない。
・変数が大文字の方が都合がいい=RAMがほぼ無い4bitマイコン等だとあり得る。この場合、ほぼアセンブラ。
・基本ハードウェア+ちょいソフト(アセンブラ)程度で、今時ならIoTの末端の各センサ等、
定期的に計測値を報告するようなプログラムはずっとやってきている。
WatchDogTimerやPowerOnResetを使いまくりなのでプログラム自体はポンコツでもいい。
だとすると、下からCを攻めてきているわけだが、これはほぼ無いパターンだから最初にそれを言うべきだ。
この場合、参考書はK&Rのみで、それ以外は全部ゴミだから捨てていい。
割り算の仕様なら、P13にもろに書いてある。
> Cでは他の多くの言語と同様、整数の割り算では切り捨てが行われて、
> 小数部が切り捨てられてしまうからである。(K&R第2版P13)
K&Rは「既にプログラミング出来る人がCを入門する用」に書いてあるから、
プログラミング自体の入門者には不向きだが、君の場合は最適だ。
一応言っておくが、ハロワがP7、コメントがP11、のP13な。本当にど頭に書いてある。
アセンブラの範囲を超えてCに踏み込んできたのなら、C流の管理方法に合わせた方がいい。
アセンブラの管理方法は、結局はアセンブラの規模用でしかなく、Cの規模には対応しづらい。
アセンブラ修得済みの人がCを修得するのは容易い。
ただし既に言ったように、世の中の「入門書」はそういう人向けではないから、K&R以外は読まなくていい。
とりあえずK&Rを頭から全部一通り読め。それでだいぶ状況が変わるはずだ。 >>147
× キャストに頼らないコードを書く
○ 『暗黙の』キャストに頼らないコードを書く
だろ。ただ、intをfloatに突っ込むと『精度が落ちる』と警告が出るはずだが。
(少なくともVC++ではそう。gccはこの辺甘々だから駄目かもしれんが)
キャスト自体が悪、というのはC++(というより型安全)の思想だが、
現実的にはCでは『明示的な』キャスト無しではまともに書けない。
ただし、『暗黙的な』キャストは当然無しには出来る。 >>150
10分という物理量と3308はどういう関係だ?
テキトーすぎて相手するに値しないんだが >>154
暗黙のキャスト?
意味わからん造語で語られても困るわ >>154
> 現実的にはCでは『明示的な』キャスト無しではまともに書けない。
ほうほう
暗黙変換を明示的なキャストにすることで
どんな「現実的」なコードが書けるんだ? おいバカ >>154, >>156
>暗黙のキャスト
integral promotion?
それとも bcc用語では暗黙の型変換のことですか? 確かにintをflotに突っ込むのは型だけ変わるじゃなくてデータも変わるからなぁ <stdint.h>とかのint8_tとかって
「プログラマが気が付かない整数型に関するミスをコンパイルする段階で(エラーとして)発見できる」
以外に使い道ってか利点ってないよね?
int8_tで定義することでプログラムの速度が上がったりはしないと思ってるんだけど 間違ってる? >>161
速度も上がらないし、そもそもコンパイル時にエラーとしても発見できない。
ただ単にコーディング時や人のソースを読む時にビット数が明確に認識できるだけ。 (通信プロトコル等の)外的要因でビット数が規定されているものを操作するコードを書くとき >>162
例えばすごく初歩的なんだけど
uint8_t型で宣言したループカウンタが500回回ったらコンパイルの時に警告でるよね。
……と思って今試したら警告レベルを最大にしてやっと出たわ。
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int
main(void)
{
for (uint_fast8_t cnt = 0; cnt < 500; cnt++) {
printf("%d\n", cnt);
}
exit(EXIT_SUCCESS);
}
これを
$ gcc -std=c99 -Wall -Wextra -Wpedantic -o inttest ./inttest.c
でやっと注意してくれる。
あれ? なんかもっと良い感じに撥ねられて(不注意な自分には)便利だなと思ったんだが,勘違いだったようだw >>161
利点というか、1byteが8bitでない環境もあるので、ポータブルなコードを書く場合は他に選択肢がないと思う それはどちらかというと静的解析の仕事じゃないかなあ。 >>164
> ……と思って今試したら警告レベルを最大にしてやっと出たわ。
最大にすれば出るのだから『便利』と言っていい。
警告レベルは自分に合わせて使うものだ。
判断する能力がないのなら、とりあえず最大にしとけ。
>>161
演算速度自体は上がらない。むしろ符号拡張等が必要になり落ちる。(事が多い)
これは通常はintがCPU内部のALU幅と同じ(つまり最速)に設定される為だ。
ただしフットプリントは減る為、キャッシュヒット率が上がり、結果的に速くなることはある。
よく分からなければ、基本的に全部 int で、明確に必要なところだけその他を使えばいい。
(同一ソースでint幅が異なる複数の処理系で動かすというような場合を除く) int8_tとか使おうとしているやつ相手に、とりあえずint使っとけとか
どんだけドヤアホなんだよ >>169
いやint8_tの利点を聞いてる時点で>>167に分があると思うぞ 現時的にはちょっとデータを保存するとかネットワーク越しに外に送るとかした時点でサイズは意識することになるから、intが無難とも言い難い。
意識できてればなんでもいいんだが… 構造体とかにint_8が入ってたらintに入れて計算してint_8に入れて
戻すのがいいのか? 計算の途中でint8_tの範囲外になる可能性があるかどうかと範囲外になった場合にどうしたいか次第だろ。 int32_tが最速だけれどsize_tと一緒に使うと型変換がいることで遅くなるんだよな >>175
何が最速化は環境によるのでは?
少なくともfast型のほうが早そうだが ごめんバカみたいな質問なんだけど
その「遅い」っていうのは実行時の速度だよね。コンパイルが遅いってことじゃないよね。
だとすると8の倍数のbit数のCPUでint<8×N>型を使ってもタイムロスって起きない気がするんだけど……。 >>177
そういうのはSSE命令とか使うXMMレジスタ使う話。
Intelコンパイラでも無いとアセンブラの話。
単純に上位ビットを0で埋める。(分遅くなる)
ただ、CPUアーキテクチャにも依存する。
95年当時はpentiumは32ビットCPUだが16ビットの方が速く、pentiumU以降で32ビットの方が速くなった。
Core2は32ビットが速く、64ビットは遅く、Core iから64ビットの方が速くなった。
(ハードレベルでも、ただ実装しただけと、最適化したのとある) encode.exe
PGM 形式の画像ファイルを入力に与え,Run Length 法によって圧縮したデータを出力す る
decode.exe
encode.exe で圧縮したデータを入力に与え,PGM 形式の画像ファイルを出力する。
これをc言語で書くにはどうすればいいですか?
osはUnix開発環境はMSYS2です。 ランレングスと画像フォーマットは何ら関係ないよ。
てかもしかしてランレングスのコードそのものを教えてもらうつもり?
学校の課題は自分でやりな。 コードはかけたのですがエラーが出ないのに圧縮するとデータサイズが大きくなるはずなのに小さくなります。それがわからないです。 >>182
私はあなたの言ってることが分からないです。 元のファイルと出来上がったファイルの中身を16進ダンプしたりして調べれば良いのでは?
それとプログラムもよーく読み直してみな。 >>182
圧縮したらデータサイズが小さくなったって悩んでるんだよね?
自分で何言ってるか分かってる??
布団も圧縮したら小さくなるぜ。 Run Length は連続データが少ないと大きくなる事があるからその辺は特に不思議はない。 でかくなる様なデータで確かめる課題かね?
ちょっとそのまんま見てみたいね PGMのランレングスは何かしら工夫してんのかな
(行単位で生列とRLを切り替えできるとか? 連続性の強い色空間を選択してるとか?) 0バイトのデータを圧縮すると間違いなく大きくなる 虚数空間にデータを書き移すから、さらに小さくなる、かも ホログラフィーみたいに3次元情報?が2次元に畳み込まれてなんて話ではないんだろう 任意のデータをその半分に出来る圧縮技法、誰か考えて SERNをハックしてLHCでマイクロブラックホールを作ってどうたらこうたらするとかなり圧縮できるよ 綴りを間違えるとホワイトホールができちゃうかもしれんぞ マジレスすると情報っていうのは消失しないと考えられているので
BH表面にエネルギー運動量テンソルの波動として,飲み込まれた物質郡の属性
(電荷など)が記録される……筈w
少なくとも現状の場の量子論と重力宇宙論ではそういう結論が出てる。
C言語とは関係ないけど,BHを記憶装置として用いるっていう考えは
突拍子もないけど理論的には可能だよねぇ,上記の理屈が正しいとすると。 ■ このスレッドは過去ログ倉庫に格納されています