[C++] Reference naar tweedimensionale const array

Pagina: 1
Acties:

  • WildernessChild
  • Registratie: Februari 2002
  • Niet online

WildernessChild

Voor al uw hersenspinsels

Topicstarter
Aanschouw het volgende stukje C++-code:
C++:
1
2
3
4
5
6
class Displayer {
  // ...
  static const GLfloat normal_block_colors[BF_NUMBER][3];
  static const GLfloat colourblind_block_colors[BF_NUMBER][3];
  // ...
}


Deze worden ergens anders in de source gedefinieerd:
C++:
1
2
3
4
5
6
7
8
9
const GLfloat Displayer::normal_block_colors[BF_NUMBER][3]
 = { { 0.73f, 0.0f, 0.73f },
 // ...
     { 2.0f * 1.0f, 2.0f * 0.4f, 2.0f * 0.0f } };

const GLfloat Displayer::colourblind_block_colors[BF_NUMBER][3]
 = { { 0.95f, 0.95f, 0.95f },
 // ...
     { 2.0f * 1.0f, 2.0f * 0.4f, 2.0f * 0.0f } };


Nu wil ik een reference maken naar één van deze arrays. Het moet een reference zijn, omdat hij op veel plaatsen in de code aangesproken wordt als:
C++:
1
yadda = block_colors[foo][bar];

en ik te lui ben om die allemaal aan te passen.

Nu dacht ik dat zo op te lossen (in de Displayer class):
C++:
1
2
  static const GLfloat **&block_colors;
  // references either normal_block_colors or colourblind_block_colors

met een assignment die een cast gebruikt (anders compileert het niet):
C++:
1
block_colors = (const GLfloat**)normal_block_colors;


Het probleem is, dat dit wel compileert, maar bij het linken krijg ik een zooi "Undefined reference to `Displayer::block_colors'".

Ik heb het idee dat ik iets heel stoms over het hoofd zie, maar ik krijg deze code met geen mogelijkheid werkend. Kan iemand hier eens zijn licht op laten schijnen? Als er een methode is zonder een reference te gebruiken (voor mijn gevoel moet een const GLfloat** ook werken) mag dat ook. Alvast bedankt!

[ Voor 1% gewijzigd door WildernessChild op 18-07-2004 20:41 . Reden: layoutfix ]

Maker van Taekwindow; verplaats en resize je vensters met de Alt-toets!


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-05 18:13
Je linker errors kan ik niet verklaren, maar wat sowieso al fout gaat is dat je een twee-dimensionale array beschouwt als een array van pointers (GLfloat**). 'Gelukkig' zijn arrays in C/C++ gewoon pointers, dus kun je de array gewoon aan een pointer van het juiste type assignen om 'm te gebruiken:
C++:
1
2
3
const GLfloat (*block_colors)[3]; 
[..]
block_colors = normal_block_colors;

Als het goed is heb je dus ook helemaal geen casts nodig.

Dit is trouwens een vrij lastig onderwerp vooral door de ingewikkelde (C) syntax. Als je niet direct duidelijk is hoe deze declaratie werkt, is het wellicht handig om even een samenvatting door te lezen (bijvoorbeeld: C Programming Tutorial: Arrays) en vervolgens dit artikel waarin de C syntax nader uitgelegd wordt: Reading C Type Declarations.

[ Voor 37% gewijzigd door Soultaker op 18-07-2004 21:20 ]


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 14:53

NMe

Quia Ego Sic Dico.

Heffen * en & elkaar niet op, waardoor er eigenlijk gewoon *block_colors staat? En dan heb je dus geen 2dim array meer...

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • Robtimus
  • Registratie: November 2002
  • Laatst online: 11:06

Robtimus

me Robtimus no like you

NMe84 schreef op 18 juli 2004 @ 21:15:
Heffen * en & elkaar niet op, waardoor er eigenlijk gewoon *block_colors staat? En dan heb je dus geen 2dim array meer...
& in het type van een declaratie is een reference, geen pointer. Pas als het aan de rechterkant van een = oid wordt gebruikt is het de adress-of operator.

Maar is **&GLfloat niet een pointer naar pointer naar reference naar GLfloat? Moet je niet eerder &**GLfloat hebben (reference naar pointer naar pointer naar GLfloat = reference naar 2D array van GLfloat)? En werkt gewoon &GLfloat[][] niet?

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-05 18:13
NMe84 schreef op 18 juli 2004 @ 21:15:
Heffen * en & elkaar niet op, waardoor er eigenlijk gewoon *block_colors staat? En dan heb je dus geen 2dim array meer...
Als je * en & als operators in een expressie gebruikt, heffen ze elkaar (bijna) op, maar bij een declaratie betekenen * en & gewoon wat anders en dan gaat dat niet op. Je kunt ze maar beter niet in verband proberen te brengen want dat is een bron van verwarring.
IceManX schreef op 18 juli 2004 @ 21:26:
Maar is **&GLfloat niet een pointer naar pointer naar reference naar GLfloat? Moet je niet eerder &**GLfloat hebben (reference naar pointer naar pointer naar GLfloat = reference naar 2D array van GLfloat)? En werkt gewoon &GLfloat[][] niet?
Pointers naar references bestaan niet; je kunt uitsluitend reference variabelen declareren. Je mag die & geloof ik wel op verschillende plaatsen zetten, maar hij werkt hoe dan ook direct op de variabele en nergens anders op.

Overigens blijft het punt dat in C/C++ een twee dimensionale array geen array van pointers is (float**). Een declaratie als float[][] werkt sowieso niet, aangezien je alleen de 'buitenste' dimensie onbepaald mag laten in C/C++ (het is geen Java!).

[ Voor 47% gewijzigd door Soultaker op 18-07-2004 21:30 ]


  • WildernessChild
  • Registratie: Februari 2002
  • Niet online

WildernessChild

Voor al uw hersenspinsels

Topicstarter
NMe84 schreef op 18 juli 2004 @ 21:15:
Heffen * en & elkaar niet op, waardoor er eigenlijk gewoon *block_colors staat? En dan heb je dus geen 2dim array meer...
Dat gaat alleen op als je ze als operators gebruikt, en niet als declaratie-thingies :)

Soultaker: zoals jij het zegt compileert het inderdaad keurig, maar ik blijf met mijn linker errors zitten :(

Maker van Taekwindow; verplaats en resize je vensters met de Alt-toets!


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-05 18:13
Staat die declaratie in de klasse of erbuiten? Als 'ie erbuiten staat moet je 'm juist niet static declareren (handig, die keywords die afhankelijk van de context een andere betekenis hebben).

  • WildernessChild
  • Registratie: Februari 2002
  • Niet online

WildernessChild

Voor al uw hersenspinsels

Topicstarter
De declaratie staat binnen de class Displayer { ... }.

Maker van Taekwindow; verplaats en resize je vensters met de Alt-toets!


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-05 18:13
Wat zegt de linker dan precies? Kun je anders een minimaal codefragment geven dat de genoemde foutmelding oplevert?

  • WildernessChild
  • Registratie: Februari 2002
  • Niet online

WildernessChild

Voor al uw hersenspinsels

Topicstarter
De linker (MinGW) zegt:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
c++  -O6 -s  -o crack-attack  Attack.o [...] obj_score_record.o    -lgl -lglu32 -lglut32 -lwsock32 
Displayer.o(.text+0xb5):Displayer.cxx: undefined reference to `Displayer::block_colors'
Displayer.o(.text+0xbf):Displayer.cxx: undefined reference to `Displayer::creep_colors'
Displayer.o(.text+0x3f2):Displayer.cxx: undefined reference to `Displayer::block_colors'
Displayer.o(.text+0x3fc):Displayer.cxx: undefined reference to `Displayer::creep_colors'
DrawBlocks.o(.text+0x38d):DrawBlocks.cxx: undefined reference to `Displayer::block_colors'
DrawBlocks.o(.text+0x424):DrawBlocks.cxx: undefined reference to `Displayer::creep_colors'
DrawBlocks.o(.text+0x43a):DrawBlocks.cxx: undefined reference to `Displayer::block_colors'
DrawBlocks.o(.text+0x483):DrawBlocks.cxx: undefined reference to `Displayer::creep_colors'
DrawBlocks.o(.text$_ZN9Displayer9drawBlockER5Blockb+0x71):DrawBlocks.cxx: undefined reference to `Displayer::block_colors'
DrawBlocks.o(.text$_ZN9Displayer9drawBlockER5Blockb+0xd8):DrawBlocks.cxx: undefined reference to `Displayer::creep_colors'
DrawBlocks.o(.text$_ZN9Displayer9drawBlockER5Blockb+0x15e):DrawBlocks.cxx: undefined reference to `Displayer::block_colors'
DrawBlocks.o(.text$_ZN9Displayer9drawBlockER5Blockb+0x276):DrawBlocks.cxx: undefined reference to `Displayer::block_colors'
DrawBlocks.o(.text$_ZN9Displayer9drawBlockER5Blockb+0x2e8):DrawBlocks.cxx: undefined reference to `Displayer::block_colors'
DrawBlocks.o(.text$_ZN9Displayer9drawBlockER5Blockb+0x4b0):DrawBlocks.cxx: undefined reference to `Displayer::block_colors'
DrawBlocks.o(.text$_ZN9Displayer9drawBlockER5Blockb+0x605):DrawBlocks.cxx: undefined reference to `Displayer::block_colors'
DrawCandy.o(.text+0x3d6):DrawCandy.cxx: more undefined references to `Displayer::block_colors' follow


Minimaal codefragment: wordt aan gewerkt...

[ Voor 22% gewijzigd door WildernessChild op 18-07-2004 21:40 . Reden: layoutfix ]

Maker van Taekwindow; verplaats en resize je vensters met de Alt-toets!


  • WildernessChild
  • Registratie: Februari 2002
  • Niet online

WildernessChild

Voor al uw hersenspinsels

Topicstarter
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Klasse {
    public:
        static void functie();
    private:
        static const int array[2][3];
        static const int(*pointer)[3];
};

const int Klasse::array[2][3] = { {1, 2, 3}, {4, 5, 6} };

void Klasse::functie() {
    pointer = array;
}

int main() {
    Klasse::functie();
    return 0;
}


Dit geeft als output:
code:
1
2
$ c++ test.cxx 
C:/DOCUME~1/Thomas/LOCALS~1/Temp/ccEJaaaa.o(.text+0x1d):test.cxx: undefined reference to `Klasse::pointer'


Edit: Borland C++Builder geeft hetzelfde, dus het is een bug in mij en niet in ld...

[ Voor 10% gewijzigd door WildernessChild op 18-07-2004 21:49 ]

Maker van Taekwindow; verplaats en resize je vensters met de Alt-toets!


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23-05 18:13
Ah ja, op regel 6 declareer je de variabele alleen maar. Om 'm daadwerkelijk te kunnen gebruiken is een definitie nodig (net zoals met alle andere variabelen en functies). Hetzelfde als je nu doet met Klasse::array dus.

Als je dit bijvoorbeeld op regel 10 invoegt:
C++:
10
const int (*Klasse::pointer)[3];

Dan werkt je code opeens prima. :)

  • WildernessChild
  • Registratie: Februari 2002
  • Niet online

WildernessChild

Voor al uw hersenspinsels

Topicstarter
Inderdaad... weer wat geleerd. Bedankt!

Maker van Taekwindow; verplaats en resize je vensters met de Alt-toets!


  • 12_0_13
  • Registratie: April 2004
  • Laatst online: 12-02 13:19
Was het sowieso niet handiger om een struct/class te maken met daarin de GLfloat[][]? Is wat netter qua typing enzo, en makkelijker met referencen.

[ Voor 4% gewijzigd door 12_0_13 op 19-07-2004 11:51 ]

Pagina: 1