2017-10-19 16 views
0

私は明示的に変更していないときにコードが変更されたy [0]の値を与える理由を知りたいと思います。未定義の動作:配列要素の値が暗黙的に/非論理的に変更される

Code Output

コード:

#include <iostream> 

int main() { 
    std::cout << "Enter total number of values of x/y" << std::endl; 
    int n; 
    std::cin >> n; 

    double x[n]; 
    double y[n]; 
    double df[n - 1][n - 1]; 

    std::cout << "Enter values of x:" << std::endl; 

    for (int i = 0; i < n; i++) { 
     std::cin >> x[i]; 
    } 

    std::cout << "Enter values of y:" << std::endl; 

    for (int i = 0; i < n; i++) { 
     std::cin >> y[i]; 
    } 

    std::cout << std::endl; 

    for (int i = 0; i < n; i++) { 
     df[i][0] = y[i + 1] - y[i]; 
    } 

    std::cout << "value of y[0] before: " << y[0] << std::endl; 

    for (int j = 1; j < n - 1; j++) { 
     for (int i = 0; i < n; i++) { 
      df[i][j] = df[i + 1][j - 1] - df[i][j - 1]; 
     } 
    } 

    std::cout << "value of y[0] after: " << y[0] << std::endl; 
} 

Iが動的に使用してメモリを割り当てる場合にも、それは[0] Yの不変の値を与える:

Iは、以下のリンクに出力を提供しています
double* x = new double[n]; 
double* y = new double[n]; 

私はこのリンクを参照しました:Value of array member changes illogically、しかし、私はどのようにそれは(コメントに記載されているように)コードを提供しないので起こります。

なぜ私のコードでは静的な配列で、動的に割り付けられていないのですか?

+2

あなたの 'df'代入ループの最後の反復で、' i == n - 1'があります。つまり、配列の最後を過ぎた 'df [n-1] [0]'にアクセスしています。その要素にアクセスすることは未定義の動作であり、発生している問題を説明する可能性があります。 –

+2

'double x [n];'は標準のC++ではありませんが、どのコンパイラを使用していますか? – user463035818

+1

さらに悪いことに、 'i == n - 1'のとき、最後のループは' df [n] 'にアクセスします。これは境界外の2つの要素です。 – chris

答えて

1

多くの場合、範囲外を読み取っているため、undefined behaviorが呼び出され、y[0]の値が変更される可能性があります。

double df[n - 1][n - 1]; 

いますが、範囲外の配列要素にアクセスしている次の文と式と:あなたが配列の境界を定義し

df[i][0] = y[i + 1] - y[i]; // everything except the y[i] 
df[i + 1][j - 1] 
df[i][j] 
df[i][j - 1]; 
df[i + 1][j - 1] 
df[i][0] = y[i + 1] - y[i] 
df[i][j] = df[i + 1][j - 1] - df[i][j - 1]; // everything 

n-1よりも大きくなるように配列の範囲を変更するかを確認してくださいどちらかインデックスは、より小さく、n-1およびnより小さく、未定義の動作を避けるために適切です。つまり、可変長配列はC++標準の一部ではありません。

+0

可変長配列がその一部ではない場合、標準のgccコンパイラは、そのようなコードを最初からコンパイルしないでください。 –

+0

@KewalShahコンパイラによってサポートされているものもありますが、適切なフラグを使用すると警告が発行されます。 – Ron

+0

@KewalShahほとんどのコンパイラは、さまざまな拡張機能をサポートしています。一部の拡張機能は暗黙的です(無効にするにはフラグまたはオプションが必要です)。他の機能は明示的です(有効にするにはフラグまたはオプションが必要です)。 gccのVLAサポートは、暗黙的にアクティブな拡張です(あなたが私に尋ねると、より良い結果をもたらす)。 –

関連する問題