handdator

Visa fullständig version : C programmering (generiska pekare)


isato
2008-01-25, 11:36
Vad gör jag för fel? om ni inte vill tala om hela lösningen så kanske en ledtråd.
jag vill byta plats på 2 värden som skall kunna vara av vliken typ so helst.


void swap(void *p, void *q, int size);


int main()
{
//int size;
int a=3;
int b=7;
printf("a=%d och b=%d",a,b);

swap(&a, &b, sizeof (a));
printf("\na=%d och b=%d",a,b);

return 0;
}



void swap(void *p, void *q, int size)
{
//int storlek=size;
void *a;
a= malloc(size);

//int tmp;
a = (void *)p;
(void *)p = (void *)q;
(void *)q = a;

free(a);


}

jwzrd
2008-01-25, 11:58
Vad gör jag för fel? om ni inte vill tala om hela lösningen så kanske en ledtråd.
jag vill byta plats på 2 värden som skall kunna vara av vliken typ so helst.


void swap(void *p, void *q, int size);


int main()
{
//int size;
int a=3;
int b=7;
printf("a=%d och b=%d",a,b);

swap(&a, &b, sizeof (a));
printf("\na=%d och b=%d",a,b);

return 0;
}



void swap(void *p, void *q, int size)
{
//int storlek=size;
void *a;
a= malloc(size);

//int tmp;
a = (void *)p;
(void *)p = (void *)q;
(void *)q = a;

free(a);


}

Du kanske ska fundera på hur du skriver ett värde till den plats en pekare pekar. a, t ex, pekar på det minnesområde malloc() returnerar en adress till. Du måste de-referera (dereference) den och sen skriva temp-värdet dit. (och sen läsa det).

Skriv vad du vill åstadkomma med svenska ord först.

Mighty
2008-01-25, 12:09
(void *)q = a;

free(a);


Du sätter q att peka på det a pekar på, men sedan frigör du det minnesområdet vilket gör att q inte kommer ha ett giltigt värde.
Lösningen kommer jag inte ge dig, men där har du ditt problem iaf

bertbert
2008-01-25, 12:14
Kör programmet i en debugger istället för att fråga här, inspektera pekarnas värden när programmet exekveras. Det är mycket lärorikt. Och nödvändigt för att hitta icke-triviala fel längre fram i icke-triviala program...

isato
2008-01-25, 13:55
Du kanske ska fundera på hur du skriver ett värde till den plats en pekare pekar. a, t ex, pekar på det minnesområde malloc() returnerar en adress till. Du måste de-referera (dereference) den och sen skriva temp-värdet dit. (och sen läsa det).

Skriv vad du vill åstadkomma med svenska ord först.

Men kan jag de-referera? jag vet inte ju inte vilken datatyp jag får in funktionen.
jag vill ta in 2 värden av ökand datatyp och byta plats på dessa när de kommer ur min swapfunktion.

alltså

int a=2;
int b=4;

swap(&a, &b);

int a=4;
int b=2;


mvh

jwzrd
2008-01-25, 14:12
Men kan jag de-referera? jag vet inte ju inte vilken datatyp jag får in funktionen.
jag vill ta in 2 värden av ökand datatyp och byta plats på dessa när de kommer ur min swapfunktion.

alltså

int a=2;
int b=4;

swap(&a, &b);

int a=4;
int b=2;


mvh

Nej det har du rätt i när jag tänker efter. Mina C-kunskaper är rostiga; jag är inte säker på hur du skulle kopiera byte för byte på ett platformsneutralt vis utan att fucka upp byte order. Men antingen memcpy() eller en enkel for-loop 'size' varv där du de-refererar pekaren som char * - sizeof (char) är 1 - och adderar motsvarande på adressen till det malloc reserverade.

typ:
int i;
for (i = 0; i < size; i++) {
*((char *)a + i) = *((char *)p + i);
}

Och sen motsvarande för att kopiera datat från a till q. Men nu gör jag din läxa =)

EDIT: vill man var duktig så ersätter man "i++" med "i += sizeof (char)". Men jag är ändå inte säker på att man inte i det fallet strular till byte order.

Trance
2008-01-25, 14:16
Rita ner på papper. En box för varje minnesbit du allokerar och rita en pil från varje pekare till respektive box. Sedan suddar du ut och ritar om pilarna genom din funktion för att sedan dra ett streck över boxen du deallokerar.

Kan kanske hjälpa dig.

Hur som helst är C ett fult jäkla språk och bra att de platser man tvingas använda det blir mindre och mindre.

[EDIT] Jag suger på C och har inte en aning om mitt tips hjälper, men det är så jag har förklarat program i urtiden då jag höll på med skiten lite.

isato
2008-01-25, 14:17
Nej det har du rätt i när jag tänker efter. Mina C-kunskaper är rostiga; jag är inte säker på hur du skulle kopiera byte för byte på ett platformsneutralt vis utan att fucka upp byte order. Men antingen memcpy() eller en enkel for-loop 'size' varv där du de-refererar pekaren som char * - sizeof (char) är 1 - och adderar motsvarande på adressen till det malloc reserverade.

typ:
int i;
for (i = 0; i < size; i++) {
*((char *)a + i) = *((char *)p + i);
}

Och sen motsvarande för att kopiera datat från a till q. Men nu gör jag din läxa =)

EDIT: vill man var duktig så ersätter man "i++" med "i += sizeof (char)". Men jag är ändå inte säker på att man inte i det fallet strular till byte order.

det löste sig

void swap(void *p, void *q, int size)
{

void *tmp=malloc(size);

memcpy(tmp, p, size);
memcpy(p, q, size);
memcpy(q, tmp, size);


}

jwzrd
2008-01-25, 14:20
det löste sig

void swap(void *p, void *q, int size)
{

void *tmp=malloc(size);

memcpy(tmp, p, size);
memcpy(p, q, size);
memcpy(q, tmp, size);


}

Det ser korrekt ut. Jag var inte säker på om du fick använda memcpy. (Glöm inte free(tmp);)

Mighty
2008-01-25, 14:21
Hur som helst är C ett fult jäkla språk och bra att de platser man tvingas använda det blir mindre och mindre.


C är ett alldeles förträffligt språk

isato
2008-01-25, 14:29
Men går det lösa utan memcpy?

Trance
2008-01-25, 14:30
C är ett alldeles förträffligt språk

Det har ett användningsområde där det är bland de bästa men det användningsområdet krymper. Som språk är* helt enkelt C inte så bra när det gäller applikationer som inte har extrema krav på prestanda. Det är för mycket pill med saker som inte skall spela någon roll, för lätt att göra fel och svårt att upptäcka fel.

En swap som tar vad som helst bör ju se ut mer såhär(OCaml):

let swap (x,y) = (y,x);;

och låta datorn hantera minnet.

*Det är självklart enbart min åsikt och ingen fakta.

Mighty
2008-01-25, 14:33
Men går det lösa utan memcpy?

Självklart!!
Som ledtråd kan du kika på det förslag jwrzd presenterade

Mighty
2008-01-25, 14:35
Det har ett användningsområde där det är bland de bästa men det användningsområdet krymper. Som språk är* helt enkelt C inte så bra när det gäller applikationer som inte har extrema krav på prestanda. Det är för mycket pill med saker som inte skall spela någon roll, för lätt att göra fel och svårt att upptäcka fel.

En swap som tar vad som helst bör ju se ut mer såhär(OCaml):

let swap (x,y) = (y,x);;

och låta datorn hantera minnet.

*Det är självklart enbart min åsikt och ingen fakta.

Beror på om man är van vid programmering av minnessnåla enheter där man gärna själv vill ha kontroll över minnet. Som språk tycker jag därför C är riktigt trevligt, men jag håller med dig att kravet på språk skrivna i C krymper allt mer i takt med kraftfullare datorer (och 4GL).

Squirrel
2008-01-25, 14:37
C är ett alldeles förträffligt språk

Han sa inte att det var dåligt. Han sa att det var fult. Och det har han rätt i.


void (*signal(int sig, void (*sighandler)(int)))(int);

Logiskt, men fult.

bertbert
2008-01-25, 14:40
Men går det lösa utan memcpy?

En bra övning är att göra det utan kopieringsrutiner och se till att det temporära utrymmet du använder är mindre. Givetvis kan du göra det direkt med pekare, titta på implementationen av rutinen du just använde!

Squirrel
2008-01-25, 14:46
Var ett tag sen för mig också, men borde inte det här fungera?


#define swap(x, y) { void *tmp = x; x = y; y = tmp; }


Irriterande att tabbar leder till "post reply" och inte indention.

Squirrel
2008-01-25, 15:24
Eller om man vill byta plats på värdena utan att byta pekarna (om man har nån annan pekare som pekar på pekarn -- ja, jag älskar också C):

#define swap(type, x, y) { type tmp = *x; *x = *y; *y = tmp; }