Eli4ph
Eli4ph

Reputation: 351

Why clang report same types as incompatible?

I want to use the pointer returned by malloc() as the name of a multi-dimensional array, thus I cast the pointer. When compiling, I got an error:

clang++ -o cast cast.cpp
cast.cpp:29:12: error: assigning to 'int8_t (*)[width]' from incompatible type
      'int8_t (*)[width]'
  int8line = (int8_t (*)[width])(array);
           ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.

But compiling with icpc on the same platform (OS X) and g++/icpc on Linux, no error is thrown.

UPDATE: The width is variable, thus can not be const.


Tested compilers are:

Mac OS X

icpc (ICC) 17.0.4 20170411

clang --version
Apple LLVM version 8.1.0 (clang-802.0.42)
Target: x86_64-apple-darwin16.6.0
Thread model: posix

Linux 2.6.32:

icpc (ICC) 14.0.0 20130728
g++ (GCC) 4.4.6 20110731

The result should be:

icpc -std=c++11 -o cast cast.cpp && ./cast 5
0   1   2   3   4
5   6   7   8   9

0   1   2   3   4
5   6   7   8   9

minimum compilable code (updated):

#include <iostream>
#include <cstdint>

using namespace std;

int main(int argc, char* argv[])
{
  if (argc != 2)
  {
    cerr << "needs one argument\n";
    exit(EXIT_FAILURE);
  }
  long width = atol(argv[1]);

  int8_t *array = static_cast<int8_t(*)>(malloc(sizeof(int8_t)*2*width));
  for (int i = 0; i < 2*width; i++)
    array[i] = i;

  for (int j = 0; j < 2; j++)
  {
    for (int i = 0; i < width; i++)
    {
      cout << static_cast<int>(array[i+j*width]);
      if (i < (width-1))
        cout << '\t';
    }
    cout << '\n';
  }

  cout << '\n';

  int8_t (*int8line)[width];
  int8line = (int8_t (*)[width])(array);
  for (int j = 0; j < 2; j++)
  {
    for (int i = 0; i < width; i++)
    {
      cout << static_cast<int>(int8line[j][i]);
      if (i < (width-1))
        cout << '\t';
    }
    cout << '\n';
  }

  free(array);
  exit(EXIT_SUCCESS);
}

Upvotes: 2

Views: 159

Answers (2)

Passer By
Passer By

Reputation: 21131

Having a non-constexpr width is called varaible length array and is not standard C++.

The type of int8line is therefore in a weird state, int8_t (*)[width] is not an actual type, resulting in the compiler producing the confusing error message.

As Zbynek Vyskovsky - kvr000 pointed out, using const long width = 5 will work, this is because it makes width a constant expression, something known at compile time. This makes the array not a variable length array.

You should probably use std::vector instead.

Upvotes: 0

Zbynek Vyskovsky - kvr000
Zbynek Vyskovsky - kvr000

Reputation: 18825

I believe it's because it's regular non-constant variable. Other compilers may recognize immutability of this variable but that kind of guess is not something specified by standard.

If you make the variable width constant, it should work:

const long width = 5;

Upvotes: 1

Related Questions