🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

20091閲覧

VC++2019において一部の警告を解決することができない

nicoyou

総合スコア129

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/12/14 12:08

編集2019/12/17 02:31

以下のソースコードを実行すると

警告 C26451 演算のオーバーフロー: 4 バイトの値に演算子 '' を使用し、結果を 8 バイトの値にキャストしています。オーバーフローを避けるため、演算子 '' を呼び出す前に値を幅の広い型にキャストしてください (io.2)。

という警告が出るのですが、警告の説明を見ても意味が理解できません

__int64型にキャストしてみたりdouble型にキャストしてみたのですが、__int64の方は解決せず、doubleは何故キャストしなければいけないのかわかりません
調べても同じような状況の例が見つからなかったので、
できればキャストせずに解決する方法があればそのほうが良いのですが、警告が出る理由と解決法を教えてください

c++

1 if (select_level < skill_data_[si].max_level) // 最大レベルでなければ 2 DrawFormatStringToHandle(add_x, Define::WIN_H - box_size_y + add_exp_y, col.black, GetFont(font_size), 3 "命中力を %.2f (+%.2f) 増加する\nレベルアップに必要なコイン %d", increase * select_level, increase, (skill_data_[si].coins_level + select_level + 1) * level_up_coins); 4 else DrawFormatStringToHandle(add_x, Define::WIN_H - box_size_y + add_exp_y, col.black, GetFont(font_size), 5 "命中力を %.2f 増加する", increase * select_level); 6 7//上記のここ2か所で警告が出る 8(skill_data_[si].coins_level + select_level + 1) * level_up_coins 9increase * select_level 10 11//下の方はdoubleの方は消えたが__int64は消えなかった 12((__int64)skill_data_[si].coins_level + select_level + 1) * level_up_coins 13(__int64)(skill_data_[si].coins_level + select_level + 1) * level_up_coins 14(double)increase * select_level

クラスのコンストラクタで、変数(配列)を初期化した際に「メンバーは必ず初期化してください」と出るのですが、
以下のコードの様に変なことをせずに警告を消す方法はありますか?

C++

1class test 2{ 3 static constexpr int a = 100; 4 int b[a]; 5 6 test(); 7} 8 9 10test::test() 11{ 12 b[0] = 0; // これがないと警告が出てしまうができれば書きたくない 13 for(int i = 0; i < a; i++) b[i] = 0; 14}

上と少し似ているのですが、Zlibの関数を使用したクラスのコンストラクタで「メンバーを初期化して」エラーが出るのですが、
これも原因が分かりません
press_buf_size_とpress_buffer_が初期化されていないというメッセージが出ます

c++

1class CompressionToStorage 2{ 3 uLong data_buf_size_; // データ用の確保したメモリサイズ 4 uLong press_buf_size_; // 圧縮後データ用の確保したメモリサイズ 5 Bytef* buffer_; // データを保存するメモリのポインタ 6 Bytef* press_buffer_; // 圧縮データを保存するメモリのポインタ 7 uLong write_size_; // 書き込み中のサイズ 8 int use_mode_; // 書き込み(1)と読み込み(2)のどちらの処理を利用しているか 9 10public: 11 CompressionToStorage(size_t Size); 12 ~CompressionToStorage(); 13} 14 15CompressionToStorage::CompressionToStorage(size_t Size) 16{ 17 write_size_ = 0; // 書き込み中サイズの初期化 18 use_mode_ = 0; // 利用モードがまだわからないので初期化する 19 data_buf_size_ = Size; // データのサイズを保存する 20 data_buf_size_ += 2048U; // 少しだけ大きめにメモリを確保する 21 buffer_ = new(std::nothrow) Bytef[data_buf_size_]; // 保存するデータより十分大きいメモリを確保 22 if (buffer_ == nullptr) 23 { 24 ERR_GL("メモリの確保に失敗しました ( size=%lu )", data_buf_size_); // エラーメッセージ 25 return; 26 } 27 28 press_buf_size_ = compressBound(data_buf_size_); // 圧縮に必要なサイズを計算 29 if (data_buf_size_ > press_buf_size_) // 計算結果があっているか確認する 30 { 31 ERR_GL("Press size error (%lu -> %lu)", data_buf_size_, press_buf_size_); // あっていなければエラーメッセージ 32 } 33 34 press_buffer_ = new(std::nothrow) Bytef[press_buf_size_]; // 圧縮後のデータを保存するメモリを確保する 35 if (press_buffer_ == nullptr) 36 { 37 ERR_GL("メモリの確保に失敗しました ( size=%lu )", press_buf_size_); // 確保に失敗すればエラーメッセージ 38 return; 39 } 40};

これも初期化してくださいエラーなのですが、以下のクラスで構造体内の
config_type
value
select_max
の3つの変数を初期化してくださいとエラーを出されますが、意味が分かりません
=0をつければなくなりましたが、構造体の定義で初期化はしたくないので原因と対処方法を教えて欲しいです

c++

1class ConfigScene : public AbstractScene 2{ 3 struct config_t 4 { 5 int config_type; // 動きのタイプ(1はon,off、2は0%~100%) 6 int value; // 保存する値 7 std::string path; // iniファイルのパス 8 std::string section; // セクション 9 std::string key; // キー 10 std::string text; // 表示するテキスト 11 12 std::string select_text[6]; // 複数の選択肢を表示する 13 int select_max; // テキストの選択肢の登録最大数 14 }; 15 16 //std::unique_ptr<BackEffectManager> back_effect_mgr_; 17 std::unique_ptr<SelectBox> select_box_; 18 std::vector<config_t> data_list_; 19 20 int count_; 21 22 void set_pad_config(bool delete_flag = false); // パッドコンフィグを登録する 23 24public: 25 ConfigScene(IOnSceneChangedListener* impl, const Parameter& parameter); 26 virtual ~ConfigScene(); 27 28 bool update() override; 29 void draw() const override; 30};

似たような内容なので、一つの質問にまとめてしまいましたが、一つでも解決方法を教えていただければ嬉しいです

win10 VC++2019 (コミュニティ)でDxライブラリを使用しています

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

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

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

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

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

cateye

2019/12/14 12:58

>構造体の定義で初期化はしたくない ・・・これは何故でしょう?
nicoyou

2019/12/14 13:02

他のクラスや構造体では定義時に初期化はしておらず、ここだけ(警告のために)書きたくないというのと 意味もなく値 (0) を入れたくないからです(もし意味があるならばわかっていないだけですが...) b[0] = 0; // これがないと警告が出てしまうができれば書きたくない これを書きたくない、というのと理由は似ています
guest

回答3

0

ベストアンサー

cpp

1class test 2{ 3 const int a = 100; 4 int b[a]; 5 6 test(); 7}

これは一見GCCの醜悪な独自拡張VLAISのようにも見えますが、それですらない不適格なコードです。

constexprを使ってaをコンパイル時定数にするか、template classにしてtemplate引数から配列の大きさを与えるか、std::vectorを使うように書き換えてください。


意味もなく値 (0) を入れたくないからです

実行時間短縮に寄与しない無意味な努力ですからやめましょう。物事をシンプルに。


そんでもってそもそも

cpp

1#include <iostream> 2 3class test 4{ 5 static constexpr int a = 100; 6 int b[a]; 7 8 test(); 9}; 10 11 12test::test() 13{ 14 //b[0] = 0; // これがないと警告が出てしまうができれば書きたくない 15 for(int i = 0; i < a; i++) b[i] = 0; 16} 17int main() {} 18

をVS2019でコンパイルしてみましたが(/W4)、再現しません。


追記

あー、コード分析か。

正直/W4で出てこない警告は無視していいと思います。

まあ本来このfor文は0を代入してるのであって、メンバー変数の初期化構文ではないので、

cpp

1test::test() : b{} {}

のようにするべきだったのではないかとは思いますが、まあ気にしなくていいと思います。


他の質問あったことをすっかり忘れてました。

press_buf_size_とpress_buffer_が初期化されていないというメッセージが出ます

ifの中でreturnしてしまっていることで、すべてのコードパスで初期化されないのが問題です。というかメモリー確保失敗はstd::quick_exitして迅速に死にましょう。というかそういう意味でnew(std::nothrow)ってあんま意味ないです。メモリーが確保できないときになにかできることがあるかはかなり微妙なところです。むしろ正常系に対してログを出して、ログが途切れたところを特定するほうが合理的な気もします。

構造体の定義で初期化はしたくないので原

そもそもC++において構造体はありません。あるのはクラスだけです。memcpyできればいい、というクラスを作りたいのであればtrivially copyable classであれば良いのでコンストラクタを書きましょう。
C++初心者に贈る強そうな人からC++のclassに関連する謎な用語を使われたときにみるもの: trivialとか#トリビアルにコピー可能なクラス(trivially copyable class)


とにかく謎の初期化したくないマインドをお持ちのようですが、やめましょう。

投稿2019/12/14 13:50

編集2019/12/16 12:22
yumetodo

総合スコア5852

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

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

nicoyou

2019/12/14 14:04

>constexprを使ってaをコンパイル時定数にするか、template classにしてtemplate引数から配列の大き >さを与えるか、std::vectorを使うように書き換えてください。 要素数は変化しないのでconstexprを使用するように変更しておきます >実行時間短縮に寄与しない無意味な努力ですからやめましょう。物事をシンプルに。 書き方が悪かったです、意味もなくしたくないというのは 「よくわからないけどこう書いたら治ったからまぁいいや」の様な考え方をしたくないということを伝えたかったです クラス内に書いた構造体のみ初期化の警告がでる理由を理解できていません
nicoyou

2019/12/15 04:48 編集

>をVS2019でコンパイルしてみましたが(/W4)、再現しません。 確認ありがとうございます 緑の波線が表示されており、エラーメッセージは同じものです コード分析を実行すれば同じ警告が出るかもしれません std::c++17とDxライブラリの設定に変更している以外は特に特殊な変更は行っていないのですが....
nicoyou

2019/12/15 05:49 編集

>まあ本来このfor文は0を代入してるのであって、メンバー変数の初期化構文ではないので、 そういうことだったんですね、初期化しているつもりで書いていました 見た目もすっきりするので、こちらの方法に書き直しました(警告も消えました) ただ、0以外の値で初期化する方法が見つけられなかったのですが、0以外の値で初期化することは可能ですか?{1}と表記すれば一番最初の配列の一番最初の値に 1 が代入されていました また、他の変数のように () で初期化することもできたのですが、あえて{}で記入すべきなのでしょうか?
yumetodo

2019/12/15 08:25

ただのaggregate初期化なのでb{ 2, 4, 1 }みたいに書けますよ。ただ、全部特定の値にするとか、順列にするとかは、そういうstd::arrayを返す関数を作るほうがコードが読みやすいかなと思います。 > 他の変数のように () で初期化することもできたのですが Uniform initializationで検索してみてください。 初心者 C++er Advent Calendar 2015 https://adventar.org/calendars/922 の記事や、 C++11 Universal Initialization は、いつでも使うべきなのか https://qiita.com/h2suzuki/items/d033679afde821d04af8 も参考になります。
nicoyou

2019/12/16 11:05

リンク等、有難うございましたm(__)m 知らなかったことをいくつか知ることが出来ました 他の警告に対する回答はもうなさそうなのでBAにさせていただきます
nicoyou

2019/12/17 00:41 編集

>ifの中でreturnしてしまっていることで、すべてのコードパスで初期化されないのが問題です。 エラーが発生した場合はクラスを破棄して続行or終了で、このクラスを使用することを考えていなかったのと、エラーメッセージが他と同じだったため気が付きませんでした >std::quick_exit このような便利な関数の存在を初めて知りました このアプリケーションは応答していません  のメッセージなく終了できるのですね new(std::nothrow)はログを出力するために使用しております 配布するものというのもあり、成功時に常にログを出し続けるとログファイルの容量がすごく増えてしまうので(繰り返し大量に実行するため)、エラー時のみにしています >そもそもC++において構造体はありません。 構造体とクラスがほぼ同じものというのは知っていましたが構造体は存在しないんですね.... もしstructがクラスだとしても、この警告は不自然に感じます 最初のコードのconfig_tについてですが、これをpublic:にすれば警告は消えます また、クラス外に書いても警告は消えます privateなメンバ構造体?の場合のみ警告が出るのはなぜですか? >とにかく謎の初期化したくないマインドをお持ちのようですが、やめましょう。 警告の理由を理解したら何かしらの方法で初期化しますm(__)m
yumetodo

2019/12/17 02:53

>成功時に常にログを出し続けるとログファイルの容量がすごく増えてしまうので そういうのはLog Levelを起動引数とかで渡せるようにするものでは。 >最初のコードのconfig_tについてですが、これをpublic:にすれば警告は消えます アクセスできる範囲が増大することによって静的解析の限界を突破しているだけでは?
nicoyou

2019/12/19 13:14

>そういうのはLog Levelを起動引数とかで渡せるようにするものでは。 確かにそのようにユーザーが指定できるものが一般的ですね... >アクセスできる範囲が増大することによって静的解析の限界を突破しているだけでは? いくつか試してみたのですが私はよくわかりませんでした そういうものと思っておくことにします ご回答ありがとうございました
guest

0

という警告が出るのですが、

コンパイルエラーがでると思いますが、本当にそのコードで警告が出るんでしょうか

投稿2019/12/14 12:42

y_waiwai

総合スコア88038

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

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

nicoyou

2019/12/14 12:53

コンパイルエラーは出ていません(警告を出されると消しておくべきだと思っているだけで動作上は(今のところ)問題ありません) 全てを乗せると長くなってしまうので一部分のみ抜粋していますが、何かおかしな点でもありますか?
y_waiwai

2019/12/14 12:55

C++のコードにはなってませんね。
nicoyou

2019/12/14 12:57 編集

全てC++のコードですよ
yominet

2019/12/16 14:26

for(int i = 0; i < b; i++) b[i] = 0;  ↓ for(int i = 0; i < a; i++) b[i] = 0; じゃないとコンパイル通らないと思いますが
nicoyou

2019/12/17 02:31

確かに書き間違えていますね、修正しておきました
guest

0

C26495 警告であるならば、VS2019を最新にアップデートしてみてください
「C26495」で検索すると情報がたくさん出てきます。

投稿2019/12/16 14:30

編集2019/12/16 14:33
yominet

総合スコア187

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

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

nicoyou

2019/12/17 00:24

VS2019は常に最新版を使用しております また、その警告で調べはしたのですが、問題を解決できるような記事を見つけることができなかったため、ここで質問させていただきました (もちろん、解決したものもあるため、それらは省いています)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問