[C] pointer controle vraagje

Pagina: 1
Acties:

  • Neptunus
  • Registratie: Januari 2001
  • Laatst online: 16-05 13:27
Ik wil voor me zelf goed begrijpen wat pionters nu inhouden en werken.

Daarvoor heb ik onderstaand stukje code gemaakt. Een string array tekst, een char pionter, array char pionter. Het is de bedoeling dat er adres verwijzigen naar de start van de strings krijgt (dus een pionter verwijzig naar a, bb, en ccc. Natuurlijk wel de start van deze strings). Deze pionter moeten dan geplaats worden in de pionter array ptekst. Nu heb ik het volgens mij aardig goed, alleen geeft de compiler aan dat op regel 19 een Warning W8069 onportable pointer conversion.

Zouden jullie eens kunnen kijken of ik de verwijzingen allemaal goed heb en of het een beetje logies is wat ik heb gemaakt. En klopt het dat die Nonportable pointer conversion Warning alleen van toepassing is als ik mijn code run om een andere os een probleem op levert. Of is het gewoon een fout in de code.

Gebruik borland c++ compiler 5.

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<stdio.h>

char tekst[ ] = {"a\0bb\0ccc\0"};
char *ptxt;
char *ptekst[10];

int main(void){
    int i;

    for(i = 0; i < 10; i++) {
       printf("tekst[%d] = %c     \n", i, tekst[i]);
    }

    ptxt = &tekst[0];

    for(i = 0; i < 10; i++) {
       //printf("tekst[%d]   = %c      \n", i, tekst[i]);
       printf("ptekst + %d = %c    \n", i, *(ptxt + i));
       ptekst[i] = *(ptxt + i);
       printf("ptekst + %d = %c    \n", i, ptekst[i]);
    }

    return 0;
}

Verwijderd

op regel 19 is de * niet nodig
oh en het is pointer .... :p

  • Neptunus
  • Registratie: Januari 2001
  • Laatst online: 16-05 13:27
Verwijderd schreef op 12 november 2004 @ 00:57:
op regel 19 is de * niet nodig
oh en het is pointer .... :p
Ik had dat mijn het coden ook al even geprobeert. Maar als ik de * weg laat in regel 19 dan krijg ik hele rare terug voer waren!

Verder heb ik even uitgezocht wat nu die error in houdt;

W8069 Nonportable pointer conversion Compiler warning
A nonzero integral value is used in a context where a pointer is needed or where an integral value is needed; the sizes of the integral type and pointer are the same.

Use an explicit cast if this is what you really meant to do.

Voor mij is het om eerlijk te zeggen een beetje onduidelijk wat ze hiermee nu bedoelen!

[ Voor 44% gewijzigd door Neptunus op 12-11-2004 01:33 ]


Verwijderd

C:
1
printf("ptekst + %d = %c    \n", i, ptekst[i]);


moet zijn

C:
1
printf("ptekst + %d = %c    \n", i, *ptekst[i]);

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 15-05 06:45
Je moet gewoon rustig nadenken over wat de types van expressies zijn. Als je meer ervaring hebt gaat dat vanzelf, maar ook als je beginner bent moet dat je kunnen lukken. De kritieke regels zijn 19 en 20:
C:
19
20
ptekst[i] = *(ptxt + i);
printf("ptekst + %d = %c    \n", i, ptekst[i]); 

Op regel 19 wil je een assignment (=) doen. Dan is het natuurlijk de bedoeling dat de expressie aan de linkerkant hetzelfde type heeft als de expressie aan de rechterkant.

Het type van ptekst is array van char*, oftewel char** (in C 'zijn' arrays eigenlijk gewoon pointers naar het type van hun element). ptekst[ i ] heeft dus als type char *. Dat is het type aan de linkerkant.

Het type van ptxt is char*. Het type van i is int dus die kun je er bij optellen, en het type van (ptxt + i) is dus nog steeds char*. Als dat het type aan de rechterkant zou zijn, zou de code wat dat betreft al kloppen (al betekent dat nooit automatisch dat de code ook doet wat je wilt). Door er nog een dereference-operator (*) voor te zetten, wordt het type aan de rechterkant char, en dat kan bijna niet kloppen. Terecht geeft de compiler daar een waarschuwing voor.

Op regel 20 gebruik je printf; het eerste argument is de formaatstring waarin je aangeeft dat de volgende argumenten respectievelijk een getal (int) en een karakter (char)zijn. Zoals al gezegd klopt het tweede argument (i) wel want dat is een int. Het derde argument is echter van type char* en dat is dus geen char! Ook dat kan niet kloppen. Vandaar, waarschijnlijk, dat je vreemde resultaten krijgt.

De oplossing is dus ook om in regel 19 de dereference-operator weg te halen, en die op regel twintig juist toe te voegen. Wat je met je code wil bereiken is me dan nog onduidelijk, maar hij zit in ieder geval een stuk logischer in elkaar. De huidige versie is eigenlijk gewoon fout, ook al wordt 'ie wel door de C-compiler geaccepteerd.

[ Voor 3% gewijzigd door Soultaker op 12-11-2004 02:49 ]


Verwijderd

Neptunus schreef op 12 november 2004 @ 01:22:
Ik had dat mijn het coden ook al even geprobeert. Maar als ik de * weg laat in regel 19 dan krijg ik hele rare terug voer waren!
De persoon hierboven had gelijk, die * mag daar niet staan in regel 19. Dat je dan rare uitvoer krijgt verbaast me niets. Ik zal je even uitleggen waarom niet. Beschouw even je stukje code met de door mij verbeterde regel 19
code:
1
2
3
4
5
for(i = 0; i < 10; i++) { 
       printf("ptxt + %d = %c    \n", i, *(ptxt + i)); 
       ptekst[i] = (ptxt + i); 
       printf("ptekst + %d = %c    \n", i, ptekst[i]); 
    }

Bedenk nu dat ptxt een char* is die wijst naar een 9 tal characters (dankzij regel 14). In je for loop ga je ptekst[i] (ook een char*) doen wijzen naar een stuk hiervan (namelijk het stuk dat begint bij character i) omdat je = (ptxt + i) doet. Als i bvb twee is, zal ptekst[2] wijzen naar karakter twee (eigenlijk het derde karakter omdat c/c++ met nul begint). Maar daarna ga je in de printf ptekst[2] uitschrijven, wat dus een pointer is en NIET het karakter wat jij voor ogen had. Daar wil je dus ptekst[i][0] of *ptekst[i] schrijven. Bemerk dat *ptekst[i] eigenlijk *(ptekst[i]) is en niet (*ptekst)[i] omdat de [] operator voorrang heeft op de * operator :)

[edit]
Soultaker was sneller en dan nog met een betere uitleg... dat goed uitleggen is nooit m'n sterkste kant geweest :P

[ Voor 6% gewijzigd door Verwijderd op 12-11-2004 01:58 ]


  • Neptunus
  • Registratie: Januari 2001
  • Laatst online: 16-05 13:27
Soultaker schreef op 12 november 2004 @ 01:47:
Je moet gewoon rustig nadenken over wat de types van expressies zijn. Als je meer ervaring hebt gaat dat vanzelf, maar ook als je beginner bent moet dat je kunnen lukken. De kritieke regels zijn 19 en 20:
Super uitleg. dat is net de zet die ik nog nodig had om alles echt goed te begrijpen.

De * op de goede plaats op regel 19 en 20 helpt inderdaad. En door de goede uitleg begrijp ik ook waar om.

Zal nog even uitleggen wat het doen was.

Maak een programma dat een regel tekst inleest/gelijk aanmaakt en opslaat in een array.
Sla daarbij de spaties niet op, maar scheidt de woorden door het nul-karakter (’\0’).
De verschillende woorden moeten benaderbaar zijn via de adressen van de eerste char's. Zet deze adressen cq pionter in een pionter array. En dit alles voor de oefening.

Moet nu alleen nog even iets bedenken hoe ik gemakelijk bv het woordnummer kan opgeven zodat deze dan als het ware uit de totaal string gehaald worden en los afgedrukt kan worden. Zat te denken aan iets van, printf("Woord: %s\n", *ptekst[2]); Maar dit werkt niet, zal wel logies zijn. Het is nu al laad en moet maar eens gaan slapen. Maar als er nog tips of ideeën zijn. Voel ik me aanbevolen.

Stel je hebt de string "Hallo\0dit\0is\0een\0test\0" en je wilt dit afdrukken. Het zou dan de bedoeling moeten zijn om het eerste (0= hallo 1 = dit) woord af te drukken zonder de rest van de string te zien.

[ Voor 26% gewijzigd door Neptunus op 12-11-2004 02:25 ]


Verwijderd

waarom typ je nou altijd "pionter" :?
het is echt wel pointer hoor :)

Verwijderd

Neptunus schreef op 12 november 2004 @ 02:05:
Moet nu alleen nog even iets bedenken hoe ik gemakelijk bv het woordnummer kan opgeven zodat deze dan als het ware uit de totaal string gehaald worden en los afgedrukt kan worden. Zat te denken aan iets van, printf("Woord: %s\n", *ptekst[2]); Maar dit werkt niet, zal wel logies zijn.
Dat is logisch ja. En je bent alweer bijna juist, maar je maakt dezelfde fout als daarnet! Een %s verwacht een char* als type, en jij geeft *ptekst[2] mee wat dus een char is. Gewoon ptekst[2] doorgeven dus, da's een char* :)
Ik ga wel nog een extra opmerking maken: dat werkt alleen omdat %s gaat printen tot hij een null-terminator tegen komt (\0). Gelukkig voor jou zijn je woorden dus gescheiden door \0 en kan dat hier. En je weet het misschien niet, maar als je bvb "test" schrijft in je C/C++ code (inclusief die quotes dus, zoals met tekst in je progje) dan wordt er achter de schermen een \0 achter de laatste t gezet voor jou. Dit \0 gedoe wil ook nog wel eens problemen geven bij beginners. Ik zie vaak dat mensen iets doen wat in essentie neerkomt op iets als
code:
1
2
3
4
5
char* mystring = new char[2];
mystring[0]='e';
mystring[1]='n';
printf( "Mijn string is %s", mystring );
delete [] mystring;

en dan vinden ze het raar dat er op het scherm niet netjes 'en' komt maar 'en' gevolgd door een hele zwik vaak rare karakters. Wel, dat komt dus omdat er geen '\0' staat en printf gaat gewoon vrolijk verder printen tot ie een \0 ziet, en print dus ook de zooi die BUITEN de grenzen van je string zit. En het is maar wat daar net in het geheugen staat natuurlijk... :P
Pagina: 1