1

I was solving a problem, and I declared the size of an array as n, before inputting n's value and it worked for the first test case but not for the second test case. Why?

P.S: I couldn't find any relevant information online.

Here is the code snippet

    int n,arr[n];
    cin>>n;
  • 3
    I guess your in undefined behavior land, 'n' is not initialized so has a random value, first time it might be 6, next time -3, which is not good. – Surt Apr 17 '20 at 16:03
  • 2
    My advice is to use a `std::vector` which is the proper dynamic array in the `c++` language. VLAs are not legal in standard `c++` and have several limitations: [https://stackoverflow.com/questions/1887097/why-arent-variable-length-arrays-part-of-the-c-standard](https://stackoverflow.com/questions/1887097/why-arent-variable-length-arrays-part-of-the-c-standard) – drescherjm Apr 17 '20 at 16:06
  • @Surt That seems helpful but it's working every time for the first test case. Why it's not causing any problem for the first time? – Keshav Garg Apr 17 '20 at 16:08
  • 2
    ***Why it's not causing any problem for the first time?*** Unfortunately some times undefined behavior appears to work as you expect even though you are breaking the rules of the language. This is the worst problem with UB. – drescherjm Apr 17 '20 at 16:09
  • 1
    VLAs aside, `n` is uninitialized. It can have any valid `int` value (`INT_MIN` to `INT_MAX`). And that value can change (is random) each time you run the program. – 001 Apr 17 '20 at 16:10
  • 2
    Relevant reading (also read the linked articles at the end): https://en.cppreference.com/w/cpp/language/ub – Jesper Juhl Apr 17 '20 at 16:14
  • 2
    VLAs aside, `n` is uninitialized. It can have any valid int value (INT_MIN to INT_MAX), or accessing it can terminate your application, format your hard drive, email your browser history to your grandmother, or even have nasal demons shoot out of your nose. Undefined behavior can be annoying that way. The best you can hope for with UB is that your program terminates. The worst that can happen is your program appears to work correctly. – Eljay Apr 17 '20 at 16:22
  • 1
    If I drive without a license every time and I've never been caught, does that mean it's legal? – eesiraed Apr 17 '20 at 18:58

2 Answers2

4
int n,arr[n];
cin>>n;

This attempts to define a VLA (variable length array). However, VLAs are not part of C++.

This might probably supported as an extension of your compiler (e.g. g++ supports as an extension). In that case, you still have a problem. When you define the array, n is uninitialized. So it triggers undefined behaviour.

You'd want to read n before defining the VLA:

int n;
std::cin >> n;
int arr[n];

Beware that VLAs are allocated on stack. So if n value is sufficiently large, you will have undefined behaviour due to overflow (= undefined behaviour). For that reason, VLAs are best avoided. You could use std::vector<int> instead.

P.P
  • 117,907
  • 20
  • 175
  • 238
3

In your example, you are using the value of n before initializing it. This is UB.

Additionaly, variable length arrays are not allowed in c++. e.g.

int n;
// compute n somehow
int arr[n];

is also not allowed.

If your program doesn't follow the rules of the language, then anything can happen, e.g. working sometimes, working on some inputs, but not others, working on some compilers, but not others, etc. Basically, you can't have any expectations of a program that has undefined behaviour.

cigien
  • 57,834
  • 11
  • 73
  • 112
  • If the program is ill formed, it won't compile. VLA is a g++ extension, while not standard, it's not "anything can happen" . – ChrisMM Apr 17 '20 at 16:07
  • @ChrisMM I'm actually confused about that. What about ill-formed-no-diagnostic-required? I was under the impression that compiler is not *guaranteed* to diagnose ill-formed programs. – cigien Apr 17 '20 at 16:09
  • @cigien But it works for me, say if you change it to `int n; cin>>n; int arr[n];` – Keshav Garg Apr 17 '20 at 16:10
  • [VLAs when compiling a C++ source with g++](//stackoverflow.com/a/28421865) – 001 Apr 17 '20 at 16:11
  • 3
    @KeshavGarg UB means *anything* can happen. e.g. I have a clock that correctly tells me the time twice a day. I wouldn't say it *works* though. – cigien Apr 17 '20 at 16:12
  • Arrays have the form: `D1 [ constant-expressionopt ] attribute-specifier-seqopt` (formatting gets lost, sorry), if it doesn't meet that (i.e., the `constant-expression` part), then it's not valid at all. Any compiler (unless using an extension) should generate an error (I don't know of any that don't). The issue here is simply UB, since by using `n` before its given a value. – ChrisMM Apr 17 '20 at 16:18
  • 3
    @KeshavGarg You cannot experimentally *test* UB. "Works for me in some specific situation" is *not* the same as "is guaranteed by the language to always produce a specific behaviour". And even if your current code does what you expect, the fact that it contains UB means your entire program is invalid and the compiler may generate *anything* for *any* part of it. And modern compilers aggressively exploit UB. It may explode at any time with any minor change. – Jesper Juhl Apr 17 '20 at 16:20
  • ill-formed, no diagnostics required vs undefined behavior (answer also explains difference between ill-formed and ill-formed, no diagnostics required): https://stackoverflow.com/questions/22180312/difference-between-undefined-behavior-and-ill-formed-no-diagnostic-message-requ – 463035818_is_not_an_ai Apr 17 '20 at 16:26
  • tl;dr: "ill-formed" requires diagnostics "ill-formed, no diagnostics required" not – 463035818_is_not_an_ai Apr 17 '20 at 16:27
  • @idclev463035818 That helps, I'll read up on that more. I've edited the answer a bit to match that. – cigien Apr 17 '20 at 16:29
  • @cigien It's very common to use `cin>>n` in place of "computing n somehow". So, Why does computing n somehow and then declaring an array doesn't work? – Keshav Garg Apr 27 '20 at 19:54