2017-06-04 2 views
2

Ich möchte den Zeiger verwenden, der von malloc() als den Namen eines mehrdimensionalen Arrays zurückgegeben wird, also ich den Zeiger werfen. Beim Kompilieren, bekam ich einen Fehler:Warum melden die gleichen Typen als inkompatibel?

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. 

Aber mit icpc auf der gleichen Plattform (OS X) und g++/icpc unter Linux kompilieren, wird kein Fehler ausgelöst.

UPDATE: Die Breite ist variabel, kann also nicht const sein.


Getestet Compiler sind:

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 

Das Ergebnis sollte:

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 

Mindest übersetzbar Code (aktualisiert):

#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); 
} 
+1

'lange Breite = 5;' Breite sollte const sein – Loreto

+3

Es ist sehr seltsam, 'malloc' in C++ zu verwenden, und fast so seltsam * in * C * zu werfen. Dies führt mich zu der Annahme, dass Ihre Frage [ein XY ist Problem] (https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem), und die Antwort auf den X-Teil (der wichtigste Teil Ihres Problems) könnte am besten von beiden gefunden werden mit 'new int8_t [width]' oder 'std :: vector '. – Sebivor

+0

[This] (http://coliru.stacked-crooked.com/a/fd11dba2af9b5213) kompiliert unter GCC, aber nicht clang. Mögliches Verhalten ist der Grund dafür, dass clang keine Zeiger auf Arrays variabler Länge akzeptiert. –

Antwort

1

Ich glaube, es ist, weil es regelmäßige nicht konstante Variable ist. Andere Compiler erkennen möglicherweise die Unveränderbarkeit dieser Variablen, aber diese Art von Schätzung ist nicht standardmäßig festgelegt.

Wenn Sie die Variable width konstant zu machen, sollte es funktionieren:

const long width = 5; 
+0

Vielleicht, aber dann, wie man 'long width = atol (argv [1])' 'erklärt, wird das Ergebnis nicht ändern? – Eli4ph

+0

@ Eli4ph: weil die Variable immer noch effektiv konstant bleibt. Dies wird von einigen der Compiler als eine Erweiterung erkannt, die jedoch von der Standardspezifikation im Allgemeinen nicht benötigt werden. –

0

eine nicht-constexpr Mit widthvaraible length array genannt wird und ist nicht Standard C++.

Der Typ int8line ist daher in einem seltsamen Zustand, int8_t (*)[width] ist kein tatsächlicher Typ, was dazu führt, dass der Compiler die verwirrende Fehlermeldung erzeugt.

Als Zbynek Vyskovsky - kvr000 pointed out, mit const long width = 5 funktioniert, ist dies, weil es width einen konstanten Ausdruck macht, etwas zur Kompilierzeit bekannt. Dies macht das Array nicht zu einem Array mit variabler Länge.

Sie sollten wahrscheinlich stattdessen std::vector verwenden.

Verwandte Themen