Avatar billede sunejens Nybegynder
16. juli 2002 - 15:04 Der er 14 kommentarer og
1 løsning

Pointers og arrays

Jeg har følgende kode:

#include <iostream>

void strcpy(char* s,  char* t);

int main()
{
char* s1 = "Sune";
char* s2 = "Jens";

  cout << s1 << endl;

  strcpy(s1, s2);

  cout << s1 << endl;

}
void strcpy (char *s, char *t){

  while (*s++ = *t++)
    ;
}

Når jeg kører koden med pointere for s1 og s2, kommer der en "Segmentation fault". Hvis jeg bruger arrays, altså char s1[] og char s2[], virker det fint. Hvorfor kan jeg ikke bruge char* s1 = "SUNE"; når det er en lovlig c-string??
Avatar billede jpk Nybegynder
16. juli 2002 - 15:13 #1
En char pointer (*) er netop kun en pointer (pegepind om du vil) til det stykke memory der indeholder teksten.
Altså skal du, hvis du vil bruge en pointer, først få fat i noget memory, det gøres typisk med new operatoren.

Fx:
char* pCh = new char[10];
Avatar billede chries Nybegynder
16. juli 2002 - 15:18 #2
gæt:

den evaluer s tilsidst og s == adresse ikke NULL

prøv:
while ( *(*s++ = *t++) )
Avatar billede chries Nybegynder
16. juli 2002 - 15:19 #3
while ( *(*s++ = *t++) ) gik ikke :-)
Avatar billede chries Nybegynder
16. juli 2002 - 15:25 #4
dir program viker vhis du ændrer:
char* s1 = "Sune";
char* s2 = "Jens";

til:
char s1[] = "Sune";
char s2[] = "Jens";
Avatar billede sunejens Nybegynder
16. juli 2002 - 15:56 #5
Nu prøvede jeg følgende:

char* s1 = new char[10];
char* s2 = new char[10];

s1 = "Sune";
s2 = "Jens";

-men jeg får stadigvæk en "Segmentation fault".

til chries: den metode havde jeg fundet frem til, men jeg vil gerne prøve at holde fast i brugen af pointere.
Avatar billede chries Nybegynder
16. juli 2002 - 16:02 #6
du kan ikke bare lave en tildeling ved c-strenge. Du er nødtil at gøre sådan:

int main()
{
    char *s1 = new char[10];
    char *s2 = new char[10];

    strcpy( s1, "Sune" );
    strcpy( s2, "Jens" );

    cout << "s1: " << s1 << endl;
    cout << "s2: " << s2 << endl;

    strcpy(s1, s2);

    cout << "s1: " << s1 << endl;

    return 0;
}
Avatar billede pedenisback Nybegynder
17. juli 2002 - 15:03 #7
Jeg vil lige tillade mig at springe ind her med en mulig forklaring, så her er hvad jeg har fundet frem til.

"Sune" er en konstant og derfor placeret i WriteProtectet område og derfor kommer der en access violation.
Følgene linie vil også genere fejl pga samme årsag:
    *s = 'G';

I gamle dage kunne man slippe afsted med det, jeg har selv brugt det 'beskidte trick' mange gange, men den går åbenbart ikke længere..ØV.

Måske med en lidt 'slappere' compiler indstilling der ikke ligger constanter i ReadOnly område ??????
Avatar billede sunejens Nybegynder
17. juli 2002 - 15:42 #8
Men hvis "Sune" var en konstant, skulle den så ikke erklæres med keyword "const", altså
char* const s1 = new char[10];

- men så kan man netop ikke tildele s1 nogen værdi, da den er "const". Jeg må indrømme jeg befinder mig lidt på usikker grund her.
Avatar billede pedenisback Nybegynder
18. juli 2002 - 10:05 #9
Under skabelsen af "Char* Const s1" er det lovligt at tildele værdier, men efterfølgene ikke muligt.
Men det gælder kun for pointeren s1, ikke for dataområde s1 peger på. dvs du kan ikke ændre pointeren s1, men *s1 = 'A' og s1[2]= 'B' er lovligt.

Jeg har forsøgt at finde en officiel forklaring på hvor linkeren ligger de forskellige variabler, men det er ikke lykkes.
Istedet har jeg været inde i disassembleren for at lure det af.
Alle variabler oprettet under en funktion er placeret i stakken.
dvs.
    char* s1 = "Sune";
    int i = 1;
det er lovligt at skrive i stakområdet via basepointeren. så man kan ændre variablen i og pointeren s1. men området s1 peger på ligger et helt andet sted som er skrivebeskyttet (ligger sammen med koden og følger med exe filen).
men hvis vi bruger:
    char* s1 = new char[10];
vil s1 stadig ligge i stakområdet, men vil pege på et nyalloceret read/write dataområde kaldet heapen (som ikke ligger i exe filen)
og til sidst
    char array[10];
disse 10 karaktere er alle placeret i stakområdet og kan derfor tilskrives værdier.

Jeg håber at du kan bruge dette til noget og at jeg har forklaret mig godt nok.
Avatar billede pedenisback Nybegynder
18. juli 2002 - 10:20 #10
hov, og så glemte jeg lige forskellen på
    char* const s1 = new char[10];
og
    char* s1 = new char[10];

der er ingen forskel i det færdige program......
const bruger du bare for at fortælle compileren at variablen må ikke ændres.
Avatar billede sunejens Nybegynder
18. juli 2002 - 12:15 #11
En overbevisne forklaring, men hvordan bruger du disassembler funktionen. Jeg bruger g++ og emacs.
Hvis du smider et svar får du points.
Avatar billede pedenisback Nybegynder
18. juli 2002 - 13:04 #12
Pokkers der fik du mig sgu!!!
jeg bruger den integrede debugger i MS VC++. Og vidt jeg kan se, bruger du linux miljø.
Men der må der også være debuggere der kan bruges, måske har Emacs en debugger del? Det er bedst med en debugger der kan "sammensmelte" exe filen med din source kode. Det er lidt nemmere at finde rundt i.

Det var ikke helt det svar du havde håbet på, så det er ok for mig at du beholder dine points.
Avatar billede soepro Nybegynder
30. juli 2002 - 14:43 #13
Den rigtige forklaring er nu den at din increment i strcpy incrementer den byte som s/t peger på - ikke selve pointeren. Dermed ligger du bare og cykler rundt i en uendelighed. Når du bruger de-reference (*) og pre-/post-increment/decrement (++x/x++ og --x/x--) er faktorernes orden ikke ligegyldig, ligesom udtrykket evalueres fra højre mod venstre, dog med precedens til de-reference.

Dit program vil virker uanset om du definerer dine variabler som char *s1 = eller char s1[] =, hvis du ændrer strcpy funktionen sådan her:

void strcpy(char *s, const char *t) /* God skik, for at vise hvilken af de to parametre du rent faktisk ændrer.
{
  for (int i = 0; t[i]; i++)
  t[i] = s[i];
}
Avatar billede chries Nybegynder
30. juli 2002 - 15:17 #14
desværre soepro, den holder ikke vand. da det er var++, vil den udføre handlingen først, derefter incrementere s.

int x = 1, y = 1;
int z = x + y++; // z = 2 ikke 3 !

Derfor vil han tildele t byte over i s og derefter flytte pointeren (* har mindre precedens end ++). Dette også virker fint, hvis variablene erklæres som:
char s1[] = "Sune";
char s2[] = "Jens";

men hvis de er erklærert som (giver exception når *t kopireres over i *s):
char* s1 = "Sune";
char* s2 = "Jens";

de placeres forskelleigt i hukommelse, derfor vil din rutine heller ikke virke (i visual c++ compiler). du kan selv prøve det i visual c++ :-) (ved ikke om gcc håndtere det anderledes)
Avatar billede soepro Nybegynder
30. juli 2002 - 15:19 #15
Og så skal statementet inde i for- løkken selvfølgelig være:

s[i] = t[i];
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester