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

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

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

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

Q&A

解決済

4回答

9518閲覧

同じ変数名の多重定義を許可したくない

aglkjggg

総合スコア769

C++

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

0グッド

0クリップ

投稿2017/03/21 17:35

編集2017/03/22 01:39

質問

forループを書くとforの反復として使う変数iだけでなくその他変数名もforループ内で重複して定義できます。
プログラムミス(バグ)が生まれる可能性が高いのでC#のようにエラー(※画像1)を出したいのですがVisual Studioにどのような設定を行えばよいでしょうか。

また、C++はなぜこのような厄介なプログラムのミス(バグ)に繋がりそうな仕様を認めてしまったのでしょうか…


画像1. C#のエラー

プログラム

cpp

1int main() 2{ 3 for (int i = 0; i < 10; i++) 4 { 5 for (int i = 0; i< 10; i++) 6 { 7 printf("%d", i); 8 } 9 printf("★%d\n", i); 10 } 11}

###出力結果
Visual Studio 2017(v141)とgcc 5.4.0で同じ出力結果が確認できました。

0123456789★0 0123456789★1 0123456789★2 0123456789★3 0123456789★4 0123456789★5 0123456789★6 0123456789★7 0123456789★8 0123456789★9

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

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

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

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

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

guest

回答4

0

ベストアンサー

プロジェクトの構成プロパティ->C/C++->コマンドラインの追加のオプションに/we4456を追加することでC4456警告のみをエラーとして扱えます。

ビルド結果例

1>------ ビルド開始: プロジェクト:CppApp1, 構成:Debug Win32 ------ 1>stdafx.cpp 1>CppApp1.cpp 1>~\cppapp1.cpp(11): error C4456: 'i' を宣言すると、以前のローカル宣言が隠蔽されます 1>~\\cppapp1.cpp(9): note: 'i' の宣言を確認してください 1>プロジェクト "CppApp1.vcxproj" のビルドが終了しました -- 失敗。 ========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========

参考:
Compiler Warnings C4400 Through C4599
/w、/Wn、/WX、/Wall、/wln、/wdn、/wen、/won (警告レベル)

投稿2017/03/22 00:30

can110

総合スコア38262

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

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

aglkjggg

2017/03/22 01:52

ありがとうございます。 やりたいことが実現できました。 ※毎回ダイアログから操作するのも面倒なのでメモ。 // エラーにする #pragma warning(error:4456) // 警告にする #pragma warning(1:4456)
can110

2017/03/22 01:55

よかったです。たしかに#pragmaでやったほうが簡単ですね。
guest

0

C# でも 6.0 からできるようになりました。

C# 6 の新機能

ところが、C# 6では、この前半のような判定は、大変な割にメリットが少ないということで、判定しない(エラーにならない)よう変更されました。

投稿2017/03/21 22:46

Zuishin

総合スコア28660

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

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

aglkjggg

2017/03/22 03:08 編集

返信ありがとうございます。 C#はC++に比べるととても厳しい制約がつけられていた時があり、C#6で少し緩和されたのですね… 今知りました><
guest

0

C++はなぜこのような厄介なプログラムのミス(バグ)に繋がりそうな仕様を...

これは誰しも気づいたとき「そっかー」と感じた経験があるのではないかと思います。
ただ本件については若干微妙な問題にも思えます。epistemeさんがおっしゃっているようなコードをあえて書きたくなる場合もあるような。

(もちろんIDEのチェック機構を使って明示的に厳しい方向へ制限するという対処はよいと思います。)

逆にC#でもラムダ記法などで充分小さなスコープが多数出現するようなケースでは、スコープを区別できることが容易であるにもかかわらず「この変数名は使えない」と言われることのほうが使いずらいと感じます。微妙な例ではありますが、以下のようなケースだと自分のコードがよくないのかC#が厳しいのか迷うことがあります。Zuishinさんのコメントを拝見するとこれはC#6だと許されるようになったんですね...

C#

1List<int> l1 = ... 2List<List<int>> l2 = ... 3l1.Select(i => l2[i].Select(i => i+1)...); 4 ^

Scalaなどはlambdaを多用するせいか、ちょっとでもスコープが変われば文句はいわれないようです。一般的に本件の仕様として何がよいのかは、それぞれの言語の記述能力やプログラミングのスタイルなどにも影響されるのではないかと、そんなことを感じました。

投稿2017/03/22 02:56

KSwordOfHaste

総合スコア18394

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

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

0

以下のようなコードもバグを生みがちなので許すべきではない、と仰ってます?

C

1{ 2 int i; 3 { 4 int i; 5 ... 6 } 7}

投稿2017/03/21 22:58

episteme

総合スコア16614

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

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

aglkjggg

2017/03/22 03:11 編集

はい。 変数名が同じでブロックが深くなるとわかりづらくなるので、そのように考えておりました。 しかし、よく考えるとブロック内で同じ名前の変数を定義してもブロック外の同じ名前の変数に影響がないので特に問題が無いかも知れませんね…。 いい反例が思いつきませんでした>< 私自身最近C#ばかり書いていて、C++が久しぶりだったので言語の違いで違和感を感じてただけかもしれません…
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問