C言語始めたばかりのレベルです。
C言語(MicrosofrC Ver6.0)で16進数の計算をしています。
配列に書かれている16進数を計算させようとしたのですが、計算結果が正しく出ません。
計算が正しく無いのか、表示のさせ方が正しく無いのかも分からない状態です。助けて下さい。
下記の書き方をすると
warning C4056: overflow in constant arithmeticのエラーが、
x= の所の (b_header[6] * 100));と
data = の所の(b_header[3] * 1000000));の行に出ます。
プログラムは以下の通りです。
charb_header[32] = {0};
/* size */
int x_size;
int y_size;
long data_size;
long x;
void main()
{
b_header[0] = 0x30;
b_header[1] = 0x80;
b_header[2] = 0x73;
b_header[3] = 0x02;
b_header[4] = 0;
b_header[5] = 0xaf;/* Y */
b_header[6] = 0x27;
b_header[7] = 0;
b_header[8] = 0xcf;/* X */
b_header[9] = 0x0f;
x_size = (int) (b_header[8]+(b_header[9]*100));
y_size = (int) (b_header[5]+(b_header[6]*100));
x =(long)(b_header[0]+(b_header[1] * 100)+(b_header[2] * 10000)+(b_header[3] * 1000000))
/ (long)(b_header[5]+(b_header[6] * 100));
data_size =(long) (b_header[0]+(b_header[1] * 100)+(b_header[2] * 10000)+(b_header[3] * 1000000));
printf("\n data_size = %d",data_size);
printf("\n y_size = %d",y_size);
printf("\n X = %d",x);
printf("\n X_size = %d",x_size);
}
No.4ベストアンサー
- 回答日時:
>b_header[5] = 0xaf; /* Y */
>b_header[6] = 0x27;
や
>b_header[8] = 0xcf; /* X */
>b_header[9] = 0x0f;
と入ってるなら、Xは4047、Yは10259の筈。
でも、
>x_size = (int) (b_header[8]+(b_header[9]*100));
>y_size = (int) (b_header[5]+(b_header[6]*100));
を実行すると、x_sizeは1707、y_sizeは4075になる。
これは合ってるだろうか?
b_header[8] = 0x00; /* X */
b_header[9] = 0x01;
の時と
b_header[8] = 0x64; /* X */
b_header[9] = 0x00;
の時
x_size = (int) (b_header[8]+(b_header[9]*100));
を実行すると、どちらも、x_sizeは100になる。
b_header[8]、b_header[9]の中身が違うのに、どうしてx_sizeが同じ値の100になってしまうのだろう?
理由は「計算式が間違ってるから」だ。
あと、
>x_size = (int) (b_header[8]+(b_header[9]*100));
>y_size = (int) (b_header[5]+(b_header[6]*100));
>x = (long)(b_header[0]+(b_header[1] * 100)+(b_header[2] * 10000)+(b_header[3] * 1000000)) / (long)(b_header[5]+(b_header[6] * 100));
>data_size =(long) (b_header[0]+(b_header[1] * 100)+(b_header[2] * 10000)+(b_header[3] * 1000000));
は、キャストするタイミングが悪い。
オーバーフローが起こった後の結果を、一生懸命intやlongにキャストしたって手遅れ。
x_size = (int)b_header[8]+(int)b_header[9]*256;
y_size = (int)b_header[5]+(int)b_header[6]*256;
x = ((long)b_header[0]+(long)b_header[1]*256L+(long)b_header[2]*65536L+(long)b_header[3]*16777216L) / ((long)b_header[5]+(long)b_header[6]*256L);
data_size =(long)b_header[0]+(long)b_header[1]*256L+(long)b_header[2]*65536L+(long)b_header[3]*16777216L;
にしないと駄目。
それより
x_size = (int)b_header[8]+(int)b_header[9]<<8;
y_size = (int)b_header[5]+(int)b_header[6]<<8;
x = ((long)b_header[0]+(long)b_header[1]<<8+(long)b_header[2]<<16+(long)b_header[3]<<24) / ((long)b_header[5]+(long)b_header[6]<<8);
data_size =(long)b_header[0]+(long)b_header[1]<<8+(long)b_header[2]<<16+(long)b_header[3]<<24;
の方が良いでしょう。掛け算よりビットシフトの方が早い。
ご丁寧な解説ありがとうございます。
全てにキャストを書かなければならなかったのですね。
何度かやっているうちに、桁の大きいものの前にだけキャストをつけてみたりしたのですが・・・。(多分その時exeが出来たと思われます)
根本的に計算のさせ方が間違っていたので、結局キャストをもう一度取ってしまい、結果コンパイルエラーになったようです。
キャストのタイミングまで考慮出来ていなかった事を教えて頂きありがとうございます(本人としては情けない限りですが)これからはタイミングを十分考慮してキャストしたり、キャストしなくてすむ方法を考えて見ます。
他の回答者様もお書きになられていたのですが、シフト演算というものをもっと勉強すると見た目もスッキリして簡単になる事を学びました。
chie65536様のように書いて頂けてさらに分かりやすかったです。
ありがとうございました。
No.6
- 回答日時:
もうほとんど他の人が述べているので指摘だけ:
integer promotion で勝手に int になっているはずなので, *その点だけなら*キャストは不要なはずです>#5. char を使ってる時点で危険なんだけど.
あと, シフトより加減算が優先されるのも注意ですね>#4.
ご回答ありがとうございます。
補足説明をして頂いたので、()でくくってみました。
皆さんのご回答を元に、
char b_header[32] = {0}; --> unsigned char b_header[32] = {0};に
16進数計算の所は
x_size = (int) (b_header[8]+(b_header[9]*100)); -->x_size = ((unsigned int)b_header[8])+((unsigned int)b_header[9]<<8);
※ご指摘を頂いた優先順位は修正ミスで()をつけ忘れた部分があった時、+が先に計算されてしまいました。
データの表示がちゃんと出なかった所も、修正しました。
printf("\n data_size = %ld",data_size);
皆様のお陰で思った通りの計算が出来ただけでなく、シフト演算が理解出来てとても嬉しかったです。
本当にありがとうございました
No.5
- 回答日時:
No.2です。
誤記訂正
>ans = (n[2] << 8) | (n[1] << 8) | n[0]
ans = (n[2] << 16) | (n[1] << 8) | n[0]
が正しい。
それでで、シフトするとchar型を超えるので、それぞれにキャストが必要。
No.3
- 回答日時:
watcomのCでコンパイルしたら同じエラーにはなりませんでした。
以下は(1)のみ直した結果です
data_size = 3162848
y_size = 4075
X = 776
X_size = 1707
(1)まず、 char b_header[32] = {0};
は unsigned char b_header[32] = {0};
にしましょう。
(2)16進数で2738030/27AF・・・
ソースでは、27AFで割るようになっていません。
(b_header[6] * 100 の部分は
(b_header[6] * 256 でしょう。 もしくは 0x0100
vc6のintは32bitだと思ったのですが、どんなコンパイルオプションでしょうか?
ご回答ありがとうございます。
>vc6のintは32bitだと思ったのですが、どんなコンパイルオプションでしょうか?
/W3 /AH /F 8000 でコンパイルしました。
コンパイルオプションも実の所あまり詳しくないので、こう書いてコンパイルして下さいと言われてそのまましております。
ワーニングレベルを高く設定していると言う事だけは分かるのですが・・・。
No.2
- 回答日時:
No.1の返答より
・キャスト不足
・n倍の間違い
はわかる。16進数だから、「n * 100」じゃなく「n * 0x100」にしないといけない。他も同様。
というよりも、なぜシフト演算と論理和使わないの?
3Byteなら、
ans = (n[2] << 8) | (n[1] << 8) | n[0]
で同じなのに(見やすいようにキャストは省いている)。
お返事ありがとうございます
>16進数だから、「n * 100」じゃなく「n * 0x100」にしないといけない。
仰る通りでした。16進数なのに0xにしなければ当然計算は正しくされませんよね。
情けない事に、ご指摘されるまで全く気づきませんでした。
何故と言われても、シフト演算を使った事が無かったので。
シフト演算を調べてみます。
No.1
- 回答日時:
「計算結果が正しく出ません」と言われてもねぇ....
・あなたはどのような出力を期待したのですか?
・実際の出力がどうなっているのですか?
この回答への補足
ご返答ありがとうございます
xの計算結果についてですが、16進数で2738030/27AFの計算結果をFD0(4048)となるようにしたいのですが、計算結果はエラーの出る前には4048にならなかったので、その後いろいろいじっているうちに、コンパイルエラーでexeが作成されなくなりました(以前のものは削除してしまい、実行結果を確認出来ません)
今は配列の中身を固定していますが、毎回同じ部分を読んで計算させたいのです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- HTML・CSS cssの display: flex;で横並びにならずに困ってます 1 2022/12/04 13:18
- HTML・CSS テキストを画面の真ん中に配置したいです。 2 2022/11/25 16:11
- HTML・CSS ヘッダーの画像にメインエリアがかぶってしまいます 1 2022/11/28 14:06
- HTML・CSS html cssのmargin 5 2022/12/03 11:04
- HTML・CSS 書籍を見つつサイト造りの練習をしているのですが、見た目が一致しません 2 2022/11/28 15:00
- HTML・CSS CSSが上手く反映されないみたいです 2 2022/11/21 16:19
- HTML・CSS htmlについて質問です! 写真のように写真の部分が?になってしまいます。 ファイルもしっかり選べて 1 2023/07/09 21:17
- PHP PHP MySql 画像を取得 1 2022/06/04 14:05
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、以下のプログラムをどう直せ 1 2022/07/09 22:16
- HTML・CSS htmltとcssのコードで 1 2022/11/26 13:37
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語での引数の省略方法
-
「指定されたキャストは有効で...
-
#define _CRT_SECURE_NO_WARNIN...
-
C言語 エラーの原因がわからな...
-
課題でつまってます・・・
-
複数桁10進数の*桁目だけを抽出...
-
数字列を3桁ごとにカンマで区切...
-
配列v2を逆順にしてv1に格納す...
-
double型の値を、一桁ずつint型...
-
C言語の配列をC++のvectorに高...
-
if と配列の組み合わせ
-
【C++】関数ポインタの使い方
-
ラップ関数とはどんなものですか?
-
このプログラミング誰か教えて...
-
Win32APIで作るコンボボックス...
-
卒業研究でよく分からないとこ...
-
C#のコンパイルエラーCS0120に...
-
C言語についてです。
-
c言語の配列を使ってサイコロを...
-
(int *)の意味
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語での引数の省略方法
-
#define _CRT_SECURE_NO_WARNIN...
-
「指定されたキャストは有効で...
-
C言語 配列と関数の練習問題
-
複数桁10進数の*桁目だけを抽出...
-
(int *)の意味
-
if と配列の組み合わせ
-
ラップ関数とはどんなものですか?
-
卒業研究でよく分からないとこ...
-
【C++】関数ポインタの使い方
-
c言語
-
足して100になるような乱数のア...
-
C言語初心者です、、、お助けく...
-
数字列を3桁ごとにカンマで区切...
-
C言語 エラーの原因がわからな...
-
実数の整数部,小数部の取得
-
課題でつまってます・・・
-
商と剰余を同時に求める(C言語)
-
C言語の配列をC++のvectorに高...
-
std::set<int> で、ある値が何...
おすすめ情報