A program like this can even be compiled! I feel confused.

Dec 20, 2013 at 5:16pm
we all know const object need to initialized when defined. But it can be initialized by a variable is really amazing!

We also know that an array can be defined only if the dimension is known when compiling, but the following program really passed the compilation, only with a warning that "i is used while uninitialized."

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;

int main() {
	int i, j=1;
	const int ci=i;
	const int cj=j;
	//const int ck;
	int a[i];
	int b[j];
	int ac[ci];
	int bc[cj];
	cout << ci<<endl<<cj << endl; 
        cout << a[0]<<b[0]<<ac[0]<<bc[0]<<endl;
	return 0;
}


who can explain this? Is this g++ 's special improvement or the c++ standard?
I mean the compiler really don't care about the value is a constant or not, it only care about it is declared as const or not.
Last edited on Dec 20, 2013 at 5:27pm
Dec 20, 2013 at 6:02pm
I won't look up and quote the standard to you, but it is acceptable to initialize a constant value with a non-constant variable in local blocks.

(At file scope, and for static local objects, the initializer must also be a compile-time constant. There are ways around that, though, if you know what you are doing, but you must be sure to explicitly mark such objects as volatile so that the compiler will not try to optimize it the wrong way.)

TL;DR
The constant value is constant from the point of declaration/initialization. The initializer itself need not be constant.
Dec 20, 2013 at 6:18pm
closed account (G30GNwbp)
These are the flags I gave the compiler:
g++ -std=c++11 -Wall -Wextra -pedantic temp.cpp

And these are the warnings I get--they seem pretty obvious to me that there is going to be problems:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
temp.cpp: In function 'int main()':
temp.cpp:9:9: warning: ISO C++ forbids variable length array 'a' [-Wvla]
  int a[i];
         ^
temp.cpp:10:9: warning: ISO C++ forbids variable length array 'b' [-Wvla]
  int b[j];
         ^
temp.cpp:11:11: warning: ISO C++ forbids variable length array 'ac' [-Wvla]
  int ac[ci];
           ^
temp.cpp:12:11: warning: ISO C++ forbids variable length array 'bc' [-Wvla]
  int bc[cj];
           ^
temp.cpp:6:15: warning: 'i' is used uninitialized in this function [-Wuninitialized]
  const int ci=i;
               ^
Dec 20, 2013 at 6:45pm
Sorry, I only answered 1/3 of your question.

You never give i a value -- hence when you use it, the compiler complains that it is not initialized. It's value could be anything when your program runs.

The variable-length array problem is because the array size has to be known at the time of compilation. i and j are automatically invalid, but so are ci and cj -- because their initializer is not a compile-time constant.

Hence, it is a "variable length array" -- the length of the array is not known at compile time.


IIRC, C++14 will support VLAs. Until then, you must compile such things with compiler-specific extensions.

Or, just do it the standard C++ way and use a vector.

1
2
3
4
  vector <int> ac( ci );

  if (ci > 0)
    cout << ac[0] << endl;

Or dynamic allocation and all the attendant boilerplate:

1
2
3
4
5
6
7
8
9
10
11
12
  int* ac = new int[ ci ];
  try
    {
    if (ci > 0)
      cout << ac[0] << endl;
    }
  catch (...)
    {
    delete [] ac;
    throw;
    }
  delete [] ac;

Hope this helps.
Dec 20, 2013 at 6:55pm
@northfly

Please copy/paste the command line used for compile and build your programs.I'm using the following:

g++ -Wall -Wextra -std=c++11 -pedantic -pedantic-errors -o qaz qaz.cpp

and here's the message for your code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
qaz.cpp: In function ‘int main()’:
qaz.cpp:9:9: error: ISO C++ forbids variable length array ‘a’ [-Wvla]
  int a[i];
         ^
qaz.cpp:10:9: error: ISO C++ forbids variable length array ‘b’ [-Wvla]
  int b[j];
         ^
qaz.cpp:11:11: error: ISO C++ forbids variable length array ‘ac’ [-Wvla]
  int ac[ci];
           ^
qaz.cpp:12:11: error: ISO C++ forbids variable length array ‘bc’ [-Wvla]
  int bc[cj];
           ^
Compilation failed.
Dec 20, 2013 at 7:58pm
we all know const object need to initialized when defined. But it can be initialized by a variable is really amazing!

const has double meaning: it always means the object is read-only, but it also can mean the value is known at compile time. In your case, ci and cj are read-only objects, whose values are not compile-time constants.

This was disambiguated in C++11 with the new keyword constexpr, which always means compile-time constant.

and yes, only constants that are known at compile time can be used as array bounds (this was going to be changed in C++14, but it didn't happen. Might happen in C++17). Your compiler is using a non-standard language extension.
Dec 20, 2013 at 10:15pm
Thanks a lot, Guys!
I think I am more clear now.
Topic archived. No new replies allowed.