Toon posts:

[C++] Char-array

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik heb een vrij simpele vraag waar hopelijk een vrij simpel antwoord op te geven is.

In het boek dat ik heb over C++ staat dat de naam van een array het geheugenadres is van het 0e element.

code:
1
2
int tientallen[5] = {10, 20, 30, 40, 50}; 
cout << tientallen << endl; //Uitvoer: geheugenadres


In de module die ik van school heb, ook over C++, staat dat wanneer ze over char-arrays beginnen dat de arraynaam een pointer is naar het 0e element.

code:
1
2
3
4
5
char plaats[6] = "Emmen";
char plaats2[6] = {'E','m', 'm', 'e', 'n'};

cout << plaats << endl; //Uitvoer: Emmen
cout << plaats2 << endl; //Uitvoer: Emmen


Nu had ik verwacht dat het bovenstaande stukje code "E" als uitvoer zou geven maar dit is niet het geval. Waarom is de uitvoer "Emmen" en niet "E" zoals ik zelf had verwacht? Heeft dit iets te maken met dat wat je in de char-array stopt een C-string is?

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

De 2 declaraties die je geeft zijn vrijwel functioneel equivalent, behalve dat 'plaats' een zero terminated string heeft (en de 2e dus theoretisch zal crashen in een release build).

Je geeft in beide gevallen een pointer naar een char-array, en cout's overload voor operator << met char* dumpt gewoon een string. Als je alleen het eerste karakter wil doen moet je plaats2[0] uitvoeren, dat is een char en zal due 'E' outputten.

Professionele website nodig?


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Je voert een C-string uit, dat is een reeks characters, beeindigd met een nul. Overigens heb je mazzel dat dit goeie output geeft, want die 0 ontbreekt, maar blijkbaar is het geheugen waar het in staat eerst op nul gezet.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:04

.oisyn

Moderator Devschuur®

Demotivational Speaker

curry684 schreef op maandag 24 januari 2005 @ 14:01:
behalve dat 'plaats' een zero terminated string heeft (en de 2e dus theoretisch zal crashen in een release build).
Nee, de elementen die niet zijn gespecificeerd worden geinitialiseerd met de default constructor (0 dus)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
curry684 schreef op maandag 24 januari 2005 @ 14:01:
De 2 declaraties die je geeft zijn vrijwel functioneel equivalent, behalve dat 'plaats' een zero terminated string heeft (en de 2e dus theoretisch zal crashen in een release build).

Je geeft in beide gevallen een pointer naar een char-array, en cout's overload voor operator << met char* dumpt gewoon een string. Als je alleen het eerste karakter wil doen moet je plaats2[0] uitvoeren, dat is een char en zal due 'E' outputten.
Dus als ik het goed begrijp komt het door cout dat het hele woord getoond wordt ipv alleen de "E". Klopt mijn gedachtengang wel dat de naam van char-array alleen de "E" van Emmen moet opleveren doordat de naam een pointer naar de char-array is? (Pointer naar het 0e element)

Verwijderd

Topicstarter
.oisyn schreef op maandag 24 januari 2005 @ 14:10:
[...]


Nee, de elementen die niet zijn gespecificeerd worden geinitialiseerd met de default constructor (0 dus)
Dat staat ook in mijn boek. Ik heb die voorbeelden ook zo ongeveer uit mijn boek en module overgenomen dus moeten kloppen :)

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Verwijderd schreef op maandag 24 januari 2005 @ 14:10:
[...]

Dus als ik het goed begrijp komt het door cout dat het hele woord getoond wordt ipv alleen de "E". Klopt mijn gedachtengang wel dat de naam van char-array alleen de "E" van Emmen moet opleveren doordat de naam een pointer naar de char-array is? (Pointer naar het 0e element)
De pointer wijst naar de string, omdat het een char* is. Je kunt 'm wel dereferencen, dan heb je de char :)
C++:
1
cout << *plaats << endl;
Dit doet wel wat jij verwacht ;)

Professionele website nodig?


Verwijderd

Topicstarter
curry684 schreef op maandag 24 januari 2005 @ 14:31:
[...]

De pointer wijst naar de string, omdat het een char* is. Je kunt 'm wel dereferencen, dan heb je de char :)
C++:
1
cout << *plaats << endl;
Dit doet wel wat jij verwacht ;)
Even voor de duidelijkheid: Ik wil graag weten waarom de hele string wordt weergegeven en niet hoe ik ervoor kan zorgen dat alleen de "E" wordt weergegeven.

Het is me nu duidelijk dat een string een pointer naar een char is, dus *char en dat de naam van de array een pointer is naar het 0e element. Dit verklaart alleen niet voor mij waarom de gehele string wordt weergegeven. Ik heb woensdag C++ tentamen en zal en moet hem halen.

Bedankt voor jullie help alvast iig!

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 15-05 23:07

MBV

Omdat een pointer naar een Char automatisch een zogeheten c-string is, en door cout ook zo behandeld wordt. cout << probeert de best leesbare output te krijgen, en doet dat door een char* te behandelen als een string. char* staat in C dan ook gelijk aan een string (effectief gezien).
Je kan het ook anders doen, met een printf("%s\n", plaats);. Met printf kan je dat helemaal beinvloeden: probeer maar eens %b of %c. Geeft allebei niet de gewenste output lijkt me zo :) Wat wel weer kan is printf("%c", *plaats); om het karakter af te drukken.

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 16-05 11:22
Je variabele is bij een array altijd een pointer naar het eerste element. Als je hier met [] een waarde achter zet, zal dit gewoon gemeten worden vanaf dat eerste element (plaats[6] is dus "plaats + 6 * (aantal bytes in van een char)"). Daarom is er ook geen verschil tussen jouw beide initialisaties.

Dat cout de hele string output komt, zoals curry684 aangeeft, dat die functie een char* binnenkrijgt, en dan net zoveel zal outputten totdat ie een \0 tegenkomt.

[ Voor 5% gewijzigd door riezebosch op 24-01-2005 15:49 ]

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

je hebt

C++:
1
2
3
4
5
6
7
char* reeks1 = "Emmen";   // => pointer naar een char array(string)
char reeks2[6] = {'E','m', 'm', 'e', 'n','\n'};  // => pointer naar een char array

cout << reeks1    << endl;    // reeks1 is een pointer naar char => volledige string uitschrijven
cout << reeks2    << endl;    // reeks2 is een pointer naar char => volledige string uitschrijven
cout << reeks1[0] << endl; // reeks1[0] is een char => slechts 1 char
cout << reeks2[0] << endl; // reeks2[0] is een char => slechts 1 char


hiermee toon ik dus aan dat de declaraties van reeks1 en reeks2 volledig EQUIVALENT zijn.
en dat ze ook beide in een gelijke manier kunnen gebruikt worden. let echter op:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
char* reeks1 = "Emmen";
char reeks2[6] = {'E','m', 'm', 'e', 'n','\n'}; 
char* reeks3 = "Emmen";

reeks1 == reeks3;    //    => false
reeks1 == reeks2;    //    => false (geen van de 3 pointer is gelijk aan de pointer van de andere
reeks2 == reeks3;    //    => false    ze staan nl op verschillende adressen)

 // strcmp = een string/char array vergelijker met 0 als return wanneer ze gelijk zijn
strcmp(reeks1,reeks2); //  => 0 de inhoud is echter van alle 3 gelijk
strcmp(reeks2,reeks3); //  => 0

/* als ik nu */  reeks3 = reeks1;   /* doe dan is */
reeks1 == reeks3;    //    => true
reeks1 == reeks2;    //    => false
// en ben ik de char array die reeks3 hiervoor bepaalde volledig kwijt

ASSUME makes an ASS out of U and ME


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:04

.oisyn

Moderator Devschuur®

Demotivational Speaker

hiermee toon ik dus aan dat de declaraties van reeks1 en reeks2 volledig EQUIVALENT zijn.
Dat is niet waar, sizeof (reeks1) geeft een grootte van een pointer, sizeof(reeks2) geeft de totale grootte van de hele array. Reeks1 is een pointer, reeks2 niet. Reeks1 kun je derehalve reassignen, reeks2 niet. Reeks2 reserveert een stukje geheugen dat je aan mag passen, reeks1 niet (daarom is het ook netter om te doen: const char * reeks1 = "...", aangezien je een string literal niet aan mag passen).

[ Voor 38% gewijzigd door .oisyn op 24-01-2005 17:35 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
MBV schreef op maandag 24 januari 2005 @ 15:32:
Omdat een pointer naar een Char automatisch een zogeheten c-string is, en door cout ook zo behandeld wordt. cout << probeert de best leesbare output te krijgen, en doet dat door een char* te behandelen als een string. char* staat in C dan ook gelijk aan een string (effectief gezien).
Je kan het ook anders doen, met een printf("%s\n", plaats);. Met printf kan je dat helemaal beinvloeden: probeer maar eens %b of %c. Geeft allebei niet de gewenste output lijkt me zo :) Wat wel weer kan is printf("%c", *plaats); om het karakter af te drukken.
Dank je wel, zo'n soort verklaring zocht ik. Heb nog ff docent op school gevraagd net voor de zekerheid en hij gaf me een zelfde soort antwoord. Dank je wel!
HIGHGuY schreef op maandag 24 januari 2005 @ 15:58:
je hebt

hiermee toon ik dus aan dat de declaraties van reeks1 en reeks2 volledig EQUIVALENT zijn.
en dat ze ook beide in een gelijke manier kunnen gebruikt worden. let echter op:
Ik vind het heel mooi dat je aantoont dat ze equivalent zijn maar dat weet ik ook en was ook de bedoeling. Heb ik met opzet gedaan om te voorkomen dat iemand tegen me zou zeggen dat ik de array anders moest schrijven.

Ik weet niet hoe het hier gaat maar van mij part mag en slotje op dit topic. Ben er helemaal uit :D

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Verwijderd schreef op maandag 24 januari 2005 @ 16:57:
[...]

Ik vind het heel mooi dat je aantoont dat ze equivalent zijn maar dat weet ik ook en was ook de bedoeling.
Lees dan aub .oisyn's opmerking hierboven nog een keer?
Ik weet niet hoe het hier gaat maar van mij part mag en slotje op dit topic. Ben er helemaal uit :D
Slotjes zijn voor foute topics, niet om af te stoppen dat iemand nog een nuttige toevoeging aan een nuttig topic kan doen ;)

Professionele website nodig?


Verwijderd

Topicstarter
curry684 schreef op maandag 24 januari 2005 @ 17:02:
[...]

Lees dan aub .oisyn's opmerking hierboven nog een keer?

[...]

Slotjes zijn voor foute topics, niet om af te stoppen dat iemand nog een nuttige toevoeging aan een nuttig topic kan doen ;)
Gedaan: Zover wou ik niet gaan met verschillen eigenlijk ;) Klopt wel natuurlijk :)

Sommige forums maken wel gebruik van slotjes als de oplossing er al is, vandaar ik het vroeg ;) En wow, mijn topic is nuttig (en dit bericht niet :P)

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

.oisyn schreef op maandag 24 januari 2005 @ 16:09:
[...]


Dat is niet waar, sizeof (reeks1) geeft een grootte van een pointer, sizeof(reeks2) geeft de totale grootte van de hele array. Reeks1 is een pointer, reeks2 niet. Reeks1 kun je derehalve reassignen, reeks2 niet. Reeks2 reserveert een stukje geheugen dat je aan mag passen, reeks1 niet (daarom is het ook netter om te doen: const char * reeks1 = "...", aangezien je een string literal niet aan mag passen).
ok je hebt gelijk:

correctie: in dit geval zijn ze voor de gegeven bewerkingen equivalent :)

ASSUME makes an ASS out of U and ME


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
curry684 schreef op maandag 24 januari 2005 @ 14:01:
De 2 declaraties die je geeft zijn vrijwel functioneel equivalent, behalve dat 'plaats' een zero terminated string heeft (en de 2e dus theoretisch zal crashen in een release build).

Je geeft in beide gevallen een pointer naar een char-array, en cout's overload voor operator << met char* dumpt gewoon een string.
Nee. Er is geen overload van operator << voor char*. Wat er wel is, is een operator<< voor std::string en een std::string ctor die een char* accepteert. Klein detail, maar dat betekent ten eerste dat je <string> moet includen als je een char* naar std::cout wil schrijven, en ten tweede dat je onverwachte effecten kunt krijgen als je een class MyString hebt met een operator char*( ).

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

MSalters schreef op dinsdag 25 januari 2005 @ 09:46:
[...]

Nee. Er is geen overload van operator << voor char*. Wat er wel is, is een operator<< voor std::string en een std::string ctor die een char* accepteert.
* curry684 mept msalters een beetje rond de oortjes met een dik pak C++-standaarden :+

Professionele website nodig?


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
HIGHGuY schreef op maandag 24 januari 2005 @ 15:58:
je hebt

C++:
1
2
3
4
5
6
7
char* reeks1 = "Emmen";   // => pointer naar een char array(string)
char reeks2[6] = {'E','m', 'm', 'e', 'n','\n'};  // => pointer naar een char array

cout << reeks1    << endl;    // reeks1 is een pointer naar char => volledige string uitschrijven
cout << reeks2    << endl;    // reeks2 is een pointer naar char => volledige string uitschrijven
cout << reeks1[0] << endl; // reeks1[0] is een char => slechts 1 char
cout << reeks2[0] << endl; // reeks2[0] is een char => slechts 1 char


hiermee toon ik dus aan dat de declaraties van reeks1 en reeks2 volledig EQUIVALENT zijn.
en dat ze ook beide in een gelijke manier kunnen gebruikt worden. let echter op:
Nee hoor, doe maar eens
cout << int( reeks1[5] ) << endl << int( reeks2[5] ) << endl;
Je bedoelt waarschijnlijk \0 ipv \n, maar dan gelden nog steeds de eerder gemaakte opmerkingen. reeks2 is een array, en die kan geconverteerd worden naar een pointer.
C++:
1
2
3
4
5
6
7
char* reeks1 = "Emmen";
char reeks2[6] = {'E','m', 'm', 'e', 'n','\n'}; 
char* reeks3 = "Emmen";

reeks1 == reeks3;    //    => false
reeks1 == reeks2;    //    => false (geen van de 3 pointer is gelijk aan de pointer van de andere
reeks2 == reeks3;    //    => false    ze staan nl op verschillende adressen)
Je eerste //false klopt niet, dat hangt af van je optimizer. Die andere twee kloppen wel, omdat reeks2 een schrijfbare array is.
C++:
1
2
3
 // strcmp = een string/char array vergelijker met 0 als return wanneer ze gelijk zijn
strcmp(reeks1,reeks2); //  => 0 de inhoud is echter van alle 3 gelijk
strcmp(reeks2,reeks3); //  => 0
Dit werkt stomtoevallig, omdat reeks1 en reeks3 wel \0-terminated zijn, en niet langer dan reeks2. strcmp( reeks2, reeks2 ) is een keiharde bug.

Sowieso wil je in C++ niet prutsen met char* dingen. std::string is veel veiliger. Dat blijkt bijv. uit het feit dat je telkens de const vergeet.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:04

.oisyn

Moderator Devschuur®

Demotivational Speaker

MSalters schreef op dinsdag 25 januari 2005 @ 09:46:
[...]

Nee. Er is geen overload van operator << voor char*.
Voor char * niet, maar voor const char * wel, en die werkt net zo goed
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  template<class charT, class traits>
    basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&,
                        const charT*);
  template<class charT, class traits>
    basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&,
                        const char*);
  //  partial specializationss
  template<class traits>
    basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&,
                       const char*);
  //   signed and unsigned
  template<class traits>
    basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&,
                       const signed char*);
  template<class traits>
    basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&,
                       const unsigned char*);


bron

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Oopsie. Die had ik dus gemist (het zijn geen std::basic_ostream members, en ik had niet verder gekeken |:( ), en een const-conversie heeft inderdaad een lagere rank dan een user-defined conversie.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

MSalters schreef op dinsdag 25 januari 2005 @ 09:55:
[...]

Nee hoor, doe maar eens
cout << int( reeks1[5] ) << endl << int( reeks2[5] ) << endl;
Je bedoelt waarschijnlijk \0 ipv \n, maar dan gelden nog steeds de eerder gemaakte opmerkingen. reeks2 is een array, en die kan geconverteerd worden naar een pointer.
oops |:(
stomme fout van me... idd ik bedoel \0
Je eerste //false klopt niet, dat hangt af van je optimizer. Die andere twee kloppen wel, omdat reeks2 een schrijfbare array is.
theoretisch zijn ze neit gelijk

ASSUME makes an ASS out of U and ME


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:04

.oisyn

Moderator Devschuur®

Demotivational Speaker

theoretisch kun je daar geen uitspraak over doen.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
De standaard over string literals:
2.13.4/2 Whether all string literals are distinct (that is, are stored in nonoverlapping objects) is implementation-defined. The effect of attempting to modify a string literal is undefined.
Moet dus in de handleiding staan.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

hmm en zo leren we ook weer bij...
van 'het is niet gelijk' naar 'reken er niet op dat het al dan niet gelijk is'
;)

ASSUME makes an ASS out of U and ME

Pagina: 1