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

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

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

Visual Studio Codeとは、Microsoft社が開発したマルチプラットフォーム対応のテキストエディタです。Visual Studioファミリーの一員でもあります。拡張性とカスタマイズ性が高く、テキストエディタでありながら、IDEと遜色ない機能を備えることができます。

C++

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

Q&A

解決済

2回答

780閲覧

C++にて関数定義の引数宣言がうまくいきません。

motch_misa_ore

総合スコア15

Visual Studio Code

Visual Studio Codeとは、Microsoft社が開発したマルチプラットフォーム対応のテキストエディタです。Visual Studioファミリーの一員でもあります。拡張性とカスタマイズ性が高く、テキストエディタでありながら、IDEと遜色ない機能を備えることができます。

C++

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

0グッド

0クリップ

投稿2022/12/24 00:17

編集2022/12/24 00:21

質問概要

C++にて関数定義を試みているのですが、なぜかうまくいきません。
配列を引数にしていますが、そこでエラーが出てしまいます。
また、カウント変数としてi,jを定義していますが宣言していないことになっているようです。

実現したいこと

単に行列の各要素を手入力してもらい、入力された行列を一覧として表示するだけです。
手入力に関する処理を関数として独立させようとしています。
しかし、引数であるカウント変数と二次元配列の箇所で謎のエラーが出てしまいます。

発生している問題・エラーメッセージ

PS C:\Users\motch\java> g++ Function1_C++_20221223.cpp -o Function1_C++_20221223 ; .\Function1_C++_20221223 Function1_C++_20221223.cpp:6:44: error: array bound is not an integer constant before ']' token double matrix_input(int i,int j,double x[NN][NN]); ^ Function1_C++_20221223.cpp:6:48: error: array bound is not an integer constant before ']' token double matrix_input(int i,int j,double x[NN][NN]); ^ Function1_C++_20221223.cpp:62:44: error: array bound is not an integer constant before ']' token double matrix_input(int i,int j,double x[NN][NN]) ^ Function1_C++_20221223.cpp:62:48: error: array bound is not an integer constant before ']' token double matrix_input(int i,int j,double x[NN][NN]) ^ Function1_C++_20221223.cpp: In function 'double matrix_input(...)': Function1_C++_20221223.cpp:64:20: error: 'i' was not declared in this scope cout << "x["<< i <<"]["<< j <<"]?----------->"; ^ Function1_C++_20221223.cpp:64:31: error: 'j' was not declared in this scope cout << "x["<< i <<"]["<< j <<"]?----------->"; ^ Function1_C++_20221223.cpp:65:12: error: 'x' was not declared in this scope cin >> x[i][j];

該当のソースコード

以下がソースコードの冒頭の抜粋です。

C++

1#include <iostream> 2using namespace std; 3int NN=10; 4 5 6double matrix_input(int i,int j,double x[NN][NN]); 7//double matrix_display 8//double matrix_multiple 9

以下が関数の定義部分です。

C++

1double matrix_input(int i,int j,double x[NN][NN]) 2{ 3 cout << "x["<< i <<"]["<< j <<"]?----------->"; 4 cin >> x[i][j]; 5 6 return x[i][j]; 7 8}

いずれも
double matrix_input(int i,int j,double x[NN][NN]);
に問題があるようです。

試したこと、確認したこと

教科書を見直しましたが、この書き方で間違っていないようです。
何が原因なのでしょうか???

以上よろしくお願いいたします。

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

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

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

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

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

itagagaki

2022/12/24 00:39 編集

ちょっと焦点が違いますが下記のQAが参考になります。C/C++では関数の引数が配列の場合、先頭のアドレスを渡すだけなので、要素数が変数ではコンパイラがコンパイル時に要素のアドレスを計算することができません。 https://teratail.com/questions/19591
thkana

2022/12/24 04:20

質問からは外れてしまう気もしますが、 > C/C++では関数の引数が配列の場合、先頭のアドレスを渡すだけ は真ですが、 > 要素数が変数ではコンパイラがコンパイル時に要素のアドレスを計算することができません は言い切るのはどうでしょう。C++ではダメですが、可変長配列という(冷遇されている?)Cのオプション規格があるので。 gcc/clangのCであれば void func(int n, char s[][n]){ printf("%s",s[0]); } int N=10; int main(void){ char str[][N]={"Hello", "world"}; func(N,str); return 0; } は通ったりします。
itagagaki

2022/12/24 06:30 編集

C99ですね。それは知っていますが、それはコンパイル時に要素のアドレスを計算できているのですか?実行時に計算しているのではないですか?そしてこの質問はC++の質問です。
thkana

2022/12/24 07:29

> それはコンパイル時に要素のアドレスを計算できているのですか? うん、言われてみれば。もっとも、C++で定数だったとしても関数の引数に渡された配列(ポインタ)のアドレスは「計算」できないけれど(引数で渡される値をコンパイル時に計算できるわけがない)。 > そしてこの質問はC++の質問です。 C/C++では...というコメントがついたので「いやCはちょっと違うよね」というコメントをさらに重ねたものでした。C++は...という話だったら黙っていたのですけれど。CとC++で違いがあるところの一つですから。
itagagaki

2022/12/25 00:41

> 関数の引数に渡された配列(ポインタ)のアドレスは「計算」できないけれど それも違います。私は要素のアドレスと言っています。
guest

回答2

0

ベストアンサー

配列の大きさとしての数値

配列の大きさとして与える数値は「定数であること」というルールが定められています。 評価結果が定数になる式 (定数式) でもかまいません。

教科書は C++ ?

重要な点は C と C++ は異なる言語であるということです。 C では配列の大きさが定数でなくてもよい場合についての規則がありますが C++ の仕様では常に定数であることを要求しています。

C++ の処理系であっても一部には拡張や緩和していることもある (ので場合によってはコンパイルが通ってしまう) というのもややこしいところですし、資料を書く人が混同しているというのもよくあることなのでひとつの資料に書いてあるからというのは必ずしも信用できません。 複雑な言語なのでそういうこともあります。

定数式

定数式の詳細な規則はややこしくて様々な言語機能が絡んでくるので単純には言えないのですが大きな原則としては

  • コンパイル時に値を確定可能である

と考えると良いと思います。

この場合に関連するルールを抜粋すると

  • リテラルは定数
  • 定数を四則演算したものは定数
  • const 付きで宣言された変数の初期化子が定数であればその変数も定数
  • constexpr 付きで宣言された変数は定数であり、初期化子が定数でないときはエラーになる

といったものがあります。 (実際には処理系の拡張として条件が緩和されている場合もあります。)

cpp

1// リテラルは定数なので OK 2void foo(int arr[10]) {} 3 4// const 付きで初期化子も定数なので n は定数である OK 5const int n = 10; 6void bar(int arr[10]) {} 7 8// 変数は const 付きだが初期化子は定数でないので NG 9#include <cstring> 10const int m = std::strlen("abcdefghi"); // これ自体は OK 11void baz(int arr[m]) {} // でも m は定数ではないので NG 12 13// constexpr 付きの変数は定数なので OK 14constexpr int q = 10; 15void qux(int arr[q]) {} 16 17// constexpr 付きの変数の初期化子は定数である必要がある 18#include <cstring> 19constexpr int r = std::strlen("abcdefghi"); // この時点で NG 20void quux(int arr[r]) {} // r の定義が出来てないので当然だめ

仮引数の調整

仮引数として現れる配列形式の宣言はポインタに型調整されます。

たとえば

cpp

1void foo(int arr[10]) {}

というような定義があれば

cpp

1void foo(int *arr) {}

と書かれたかのように読み替えられる規則です。

二次元配列の場合はたとえば

cpp

1void bar(int arr[5][10]) {}

cpp

1void bar(int (*arr)[10]) {}

に読み替えられます。

なので想定していない型でうっかり通ってしまうということが起こります。

cpp

1void foo(int arr[5][10]) {} 2 3int main(void) { 4 int arr[3][10]; 5 // 想定より小さい配列を渡せてしまう! 6 foo(arr); 7}

配列については (歴史的事情で) こういった特別なルールがいくつかあります。

どうすべきなのか

おそらく質問者の状況では NN

cpp

1const int NN=10;

とするか

cpp

1#define NN 10

とするのが最も簡単な解決方法です。

ただ、配列の特殊ルールは (低レイヤの事情を考えると有用ではあるのですが) 扱いにくさがあり、 std::arraystd::vector といった便利なライブラリを使ったほうがよいかもしれません。 それはそれで二次元データを十分に扱いやすくできておらず将来の仕様に入れるべく議論が続いているのですがなかなか結論が出ずに先送りが続いています。

投稿2022/12/24 07:17

編集2022/12/24 07:21
SaitoAtsushi

総合スコア5444

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

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

motch_misa_ore

2023/01/03 12:34

できました!ありがとうございました!
guest

0

NNの定義はdefineでしないとダメですね

投稿2022/12/24 00:25

y_waiwai

総合スコア87747

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

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

itagagaki

2022/12/24 00:31

というか変数ではなく定数でないといけないということ
thkana

2022/12/24 04:22

C++なら const int NN=10; とするのが好みだなぁ。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問