I wrote a simple program to reproduce the warning.
OS: Ubuntu 9.10
GCC (Ubuntu 4.4.1-4ubuntu9) 4.4.1
My test program which triggers the warning:
==========================================
#include <iostream>
using namespace std;
void test(int *array1d, int rows, int columns) {
int (*array2d)[columns] = reinterpret_cast<int (*)
[columns]>(array1d);
int i = 0, j = 0;
if (i == j) {
cout<<array2d[i][j]<<endl;
} else {
cout<<array2d[i][j]<<endl; /* warning is generated for this
line */
}
}
int main() {
int rows = 10, columns = 10;
int *array1d = new int[rows*columns];
for(int i = 0; i < rows*columns; ++i) array1d[i] = i;
test(array1d, rows, columns);
delete []array1d;
return 0;
}
=====================================
I made small changes to eliminate the warning.
=====================================
#include <iostream>
using namespace std;
void test(int *array1d, int rows, int columns) {
int (*array2d)[columns] = reinterpret_cast<int (*)
[columns]>(array1d);
int i = 0, j = 0;
int tmp = array2d[i][j]; /* this line is the difference */
if (i == j) {
cout<<tmp<<endl; /* this line is the difference */
} else {
cout<<tmp<<endl; /* this line is the difference */
}
}
=====================================
Or
=====================================
#include <iostream>
using namespace std;
void test(int *array1d, int rows, int columns) {
int (*array2d)[columns] = reinterpret_cast<int (*)
[columns]>(array1d);
++array2d;--array2d; /* this line is the difference */
int i = 0, j = 0;
if (i == j) {
cout<<array2d[i][j]<<endl;
} else {
cout<<array2d[i][j]<<endl;
}
}
=====================================
It seemed a bogus warning. But it actually made my real program crash.
So I have two questions
1)
int *array1d = new int[rows*columns];
int (*array2d)[columns] = reinterpret_cast<int (*)[columns]>(array1d);
My goal is to use *array2d* like this - array2[i][j].
Is this statement supposed to work according to C++ spec? Note: the
variable *columns* cannot be determined at run time.
2) If answer to question 1) is Yes, why the warning is generated?
Following is the key part which triggers the warning:
int (*array2d)[columns] = reinterpret_cast<int (*)
[columns]>(array1d);
if (i == j) {
cout<<array2d[i][j]<<endl;
} else {
cout<<array2d[i][j]<<endl; /* warning is generated for this
line */
}
I observed several interesting things.
1) After reinterpret_cast, if *array2d* is NOT used before the if-else
statement, use of *array2d* in else branch triggers the warning. In
this case, it seems type of the pointer *array2d* CANNOT be corrected
determined so that result of pointer arithmetic may not wrong.
2) After reinterpret_cast, if *array2d* is used (e.g. ++array2d)
before the if-else statement, use of *array2d* in else branch does NOT
trigger the warning.
Hope I describe the problem clearly.
Anyone else has encountered this problem before?
Thanks
Gerald
I don't think so. I also don't think there's any need: if you just
take the address of the start of a row you can step through one int at
a time.
> I observed several interesting things.
> 1) After reinterpret_cast, if *array2d* is NOT used before the if-else
> statement, use of *array2d* in else branch triggers the warning. In
> this case, it seems type of the pointer *array2d* CANNOT be corrected
> determined so that result of pointer arithmetic may not wrong.
> 2) After reinterpret_cast, if *array2d* is used (e.g. ++array2d)
> before the if-else statement, use of *array2d* in else branch does NOT
> trigger the warning.
>
> Hope I describe the problem clearly.
> Anyone else has encountered this problem before?
I think it's an aliasing violation. Yes, lots of people. :-)
Andrew.