質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.44%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

853閲覧

C言語において最適化オプションの有無で配列の出力結果が異なる

shupira

総合スコア7

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

2グッド

0クリップ

投稿2023/05/11 17:26

編集2023/05/12 05:15

実現したいこと

最適化オプションの有無に関わらず同じ結果を出力させたい

起こっていること

C言語で画素値を読み込んで配列に格納するプログラムを組んだのですが、最適化オプションを付けた時とつけなかった時で以下のソースコードの62行目の出力が異なります。

期待する動作はimg[0]、すなわちimgという配列に格納した先頭の数値がprintfで出力されることです。
しかし、実際には最適化オプションの有無で以下のように結果が異なります。

最適化オプションあり(下1行目):配列の先頭に格納された値が出力される(下記データ群の画素値の最初の値である50が出力される)
最適化オプションなし(下2行目):配列の末尾に格納された値が出力される(下記データ群の画素値の最初の値である90が出力される)

指定したgccのオプションは以下です。

gcc

1gcc sample.c -O -Wall...最適化あり 2gcc sample.c -Wall...最適化なし

該当のソースコード

C

1#include <stdio.h> 2#include <stdbool.h> 3#include <string.h> 4#include <stdlib.h> 5 6 7#define HEIGHT 256 8#define WIDTH 256 9 10 11//do not support comments in the header section. 12bool is_correct_PNM_style(FILE *fp, char *magic_number, int *width, int *height, int *max_intensity); 13void load_gray_img(FILE *fp, unsigned char img[]); 14 15int main(int argc, char *argv[]){ 16 char *file_name = argv[1]; 17 char magic_number[2]; 18 int height, width; 19 int max_intensity; 20 unsigned char img[HEIGHT * WIDTH];//for P2,P5 21 unsigned char dst_img[HEIGHT * WIDTH];//for P2,P5 22 unsigned char color_img[HEIGHT * WIDTH * 3];//for P3,P6 23 unsigned char dst_color_img[HEIGHT * WIDTH * 3];//for P3,P6 24 FILE *fp; 25 errno_t error; 26 bool correct_PNM_style = false; //if the format of PNM is correct, this is true. 27 28 29 if(argc != 2){ 30 printf("Usage: %s <file_name>\n", argv[0]); 31 exit(1); 32 } 33 34 error = fopen_s(&fp, file_name, "rb"); 35 36 if(error != 0){ 37 printf("Could not open %s.\n", argv[1]); 38 fclose(fp); 39 exit(1); 40 } 41 42 correct_PNM_style = is_correct_PNM_style(fp, magic_number, &width, &height, &max_intensity); 43 44 if(correct_PNM_style == false){ 45 printf("Check PNM style.\n"); 46 fclose(fp); 47 exit(1); 48 } 49 50 load_gray_img(fp, img); 51 fclose(fp); 52} 53 54void load_gray_img(FILE *fp, unsigned char img[]){ 55 unsigned char pixel_value = 255; 56 int i = 0; 57 58 for(i = 0; i < HEIGHT * WIDTH; i++){ 59 fscanf_s(fp, "%hhu", &pixel_value); 60 img[i] = pixel_value; 61 } 62 printf("%d\n", img[0]); 63}

試したこと

配列のサイズとプログラムが小さい場合(格納するだけ)に配列の先頭の値を出力することを確認した。
for文内で用意されるpixel_valueの値が正しいことを確認した。
ここで正しいとはマジックナンバーがP2であるpgmファイルの画素値と上記の59行目でpixel_valueに格納される値が一致していることを指す。
なお、画素値とは下記の4行目以降の数値群を指す。

P2 256 256 255 50 46 49 52 52 58 55 57 50 49 44 43 43 44 38 39 40 ... 11 13 12 13 15 13 17 26 31 29 32 44 53 67 90

環境

Windows 10 Pro
gcc (tdm64-1) 10.3.0

tatsu99👍を押しています
yukkeorgを押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2023/05/11 17:50

どのような OS / C 言語系でどのようなオプションを指定して/しないで発生しているのでしょうか。
y_waiwai

2023/05/11 22:57

その実行結果にどういう不具合があって、それをどうしたいというはなしなんでしょうか。 問題が見えません
thkana

2023/05/11 23:40

現象自体や試したことについて ・「xxと同じ」「期待通り」「正しい」というようなあなたの判断結果だけではなく、そのように判断するに至った具体的な(実際に観察した)データを示してください。 ・他人が「全く同じこと」を試せるだけの情報を提示してください。コンパイラは何、コンパイルオプションは何、関数の呼び出しが適切なのか、また与えた入力ファイルはどんなものなのか等々。 問題を解決できないでいるあなたが削ってしまった情報が実は必要なものである、というケースは十分に考えられます。
shupira

2023/05/12 04:51

jimbe様 C言語系の系が理解できませんでしたがgccのバージョンと解釈して記載しました。 y_waiwai様 期待する動作を書いてみましたご確認ください。 thkana様 判断基準を実データの一部とともに記述しました 「全く同じこと」を試していただきたいのですがどうも65000程のデータはさすがに省略させていただきました。 データ自体は授業で提供されたものであるため適当な256*250サイズのグレー画像について実験していただければと思います。
jimbe

2023/05/12 04:51

load_gray_img 関数の引数があっていないようです。
shupira

2023/05/12 04:58

jimbe様 失礼いたしました。 修正いたしました。
int32_t

2023/05/12 05:14

load_gray_img() に渡している src_gray_img がどこにも宣言されていません。
shupira

2023/05/12 05:16

int32_t様 度々申し訳ございません。 ブラウザバックからの修正は反映されないのですね。 再度修正いたしました。
otn

2023/05/12 06:17

コンパイルが通らないコードなので、このコードについてコメントできず、一般論ですが、バグのあるプログラムだと最適化で結果が変わり得ます。 「最適化オプションで結果が変わる」という認識を一旦捨てて、「プログラムにバグがある」という観点でデバッグすると良いかと思います。
guest

回答2

0

ベストアンサー

gcc (tdm64-1) 10.3.0

TDM ということは、たしか fscanf_s() の実装は MSVCRT ですよね。古い MSVCRT だと %hhu に対応してなくて %u と解釈されるそうです。 その場合、&pixel_valueunsigned int へのポインタと解釈されて、pixel_value 付近のスタックを破壊します。

fscanf_s() の結果を unsigned int で受け取るといいかもしれません。

c

1 unsigned int pixel_value; 2 fscanf_s(fp, "%u", &pixel_value);

投稿2023/05/12 05:39

int32_t

総合スコア21186

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shupira

2023/05/12 06:12

無事期待する動作を導き出せました!
guest

0

配列のサイズとプログラムが小さい場合(格納するだけ)に期待通りの動きをすることを確認した。

1つ考えられる可能性として、渡す配列が正しく取られていない、ということがありえます。スタックに取られる自動変数は容量が限られますので、スタックを食いつぶすほどの容量を配列で使ってしまうと正しい動作をしません。

……というように、呼ぶ側の問題も考えられますので、mainまで書いて再現できるコードとしてご提示いただいたほうが、検証もやりやすいです。

投稿2023/05/11 23:50

maisumakun

総合スコア145295

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shupira

2024/03/22 00:14

回答ありがとうございます。 ベストアンサーは別の方を選ばせていただきましたが、こちらの回答も非常に参考になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.44%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問