0

I want to know why does my code give a changed value of y[0] when I am nowhere changing it explicitly. I have provided the output in the link below:

Code Output

Code:

#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;
}

Also, it gives an unchanged value of y[0] if I dynamically allocate memory using:

double* x = new double[n];
double* y = new double[n];

I referred to this link: Value of array member changes illogically, but I couldn't get a clear answer about how is it happening as it doesn't provide any code (as mentioned in the comments).

I want to know why is this happening in my code with static arrays and not dynamically allocated ones?

Kewal Shah
  • 1,131
  • 18
  • 29
  • 2
    On the last iteration of your `df` assigning loop you have `i == n - 1`. That means you are accessing `df[n-1][0]` which is one past the end of the array. Accessing that element is undefined behavior and may explain any problem you are having. – François Andrieux Oct 19 '17 at 15:36
  • 2
    `double x[n];` is not standard c++, what compiler are you using? – 463035818_is_not_an_ai Oct 19 '17 at 15:37
  • 1
    Worse, when `i == n - 1`, the last loop accesses `df[n]`, which is two elements out of bounds. – chris Oct 19 '17 at 15:37
  • And please be more clear on what is the input, output and expected output. You are changing the value of `y[0]` here `std::cin >> y[i];` – 463035818_is_not_an_ai Oct 19 '17 at 15:38
  • @tobi303 , I am using gnu compiler c++11 – Kewal Shah Oct 19 '17 at 15:40
  • Use `-Wall -Werror` when you compile. – stark Oct 19 '17 at 15:41
  • Your code has at least two places where it has undefined behavior the loop that does `df[i][0] = y[i + 1] - y[i];` goes past the end if `y`, and the nested loop also goes past the end when `i` is `n-1`. Another potential error is that you run your `j` up to `n-1`, when you probably wanted to run your `i` up to `n-1`. Run your code through valgrind to catch other possible errors. – Sergey Kalinichenko Oct 19 '17 at 15:41
  • @tobi303 , the input is clearly provided in my output link. I am asking the user to enter y[0]'s value in the line you mentioned. But it changes to some ambiguous value later. – Kewal Shah Oct 19 '17 at 15:43
  • @FrançoisAndrieux , thank you for pointing out the problem, but then how does dynamically allocating memory give me the correct output? – Kewal Shah Oct 19 '17 at 15:47
  • @KewalShah Undefined behavior means that the behavior can change for any reason, such as changing your allocation strategy. Eliminate the undefined behavior and both strategies should work. – François Andrieux Oct 19 '17 at 15:48
  • @dasblinkenlight , thank you for your answer, but how is this undefined behaviour in my loop changing the value of the very first array element of y to 15? – Kewal Shah Oct 19 '17 at 15:53
  • @KewalShah Undefined behavior can do *anything*! Changing the first element in an array to 15 is far from the most bizarre symptom. Undefined behavior is known to cause code that should have happened before the undefined behavior is encountered to change. – François Andrieux Oct 19 '17 at 15:54
  • @FrançoisAndrieux , oh thanks (seems really dangerous!). – Kewal Shah Oct 19 '17 at 15:57
  • @stark , thanks for the suggestion, will use it now on – Kewal Shah Oct 19 '17 at 16:11
  • @Kewal Shah: You are certainly *not* using c++11. You are using gnu++11 most likely or some other non-standard dialect. C++11 will not allow you to declare the arrays the way you declare them in your code. – AnT stands with Russia Oct 19 '17 at 17:10
  • @AnT , I _am_ using `-std=c++11` and not `gnu++11` tag with gcc. – Kewal Shah Oct 19 '17 at 17:19
  • @Kewal Shah: Well, I guess, in order to whip gcc into standard-compliance you'd also need `-pedantic`/`-pedantic-errors`. `-std=c++11` alone is not sufficient. – AnT stands with Russia Oct 19 '17 at 17:27
  • @AnT Yes thanks, at least that is what I learnt in the comments in the Answer. – Kewal Shah Oct 19 '17 at 17:39

1 Answers1

1

You are reading out of bounds on numerous occasions thus invoking undefined behavior which may result in modified y[0] value. You defined the array bounds with:

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

but with the following statements and expressions you are accessing array elements out of bounds:

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

Either modify the array bounds to be greater than n-1 or make sure the indexes are less than n-1 and n where appropriate to avoid undefined behavior. That being said, variable-length arrays are not part of the C++ standard.

Ron
  • 14,674
  • 4
  • 34
  • 47
  • If variable-length arrays aren't a part of it, shouldn't the standard gcc compiler stop such code from compiling in the first place? – Kewal Shah Oct 19 '17 at 16:04
  • @KewalShah Some compilers support it, warning is issued when using appropriate flags. – Ron Oct 19 '17 at 16:05
  • @KewalShah Most compilers support various extensions. Some of extensions are implicit (you need a flag or option to disable it) while others are explicit (you need a flag or option to enable it). gcc's VLA support is an implicitly active extension (which does way more harm than good if you ask me). – François Andrieux Oct 19 '17 at 16:10
  • @FrançoisAndrieux So I should use `-Wall -Werror` every time I compile, right? – Kewal Shah Oct 19 '17 at 16:15
  • @KewalShah You should use the first one definitely. And maybe `-Wextra` and `-pedantic`. – Ron Oct 19 '17 at 16:16
  • @Ron Thanks, I think `-pedantic` will be a good option. Just referred https://stackoverflow.com/questions/2855121/what-is-the-purpose-of-using-pedantic-in-gcc-g-compiler – Kewal Shah Oct 19 '17 at 16:25