|
| Pointer til funktion Fra : Thomas Schulz |
Dato : 19-04-01 12:49 |
|
I "The C++ Programming Language", Special Edition, side 157 er følgende
eksempel:
typedef void (*PF)();
PF edit_ops[] = {&cut, &paste, ©, &search};
PF file_ops[] = {&open, &append, &close, &write};
PF* button2 = edit_ops;
PF* button3 = file_ops;
Og så står der, at man fx kan kalde en funktion således "button2[2];"
Det meste af ovenstående er egentligt logisk nok, der initialiseres et array
of funktions pointere..
Men.. Hvad er det for en typedef deklaration!?! Tidligere i bogen er
"typedef" beskrevet som bruges som følgende: "typedef long int32". Det er jo
logisk nok.
Det lader til at typedef fungerer sådan her:
navn__da-der-er-mellemrum-samme-type-som__navn (bare læst omvendt :).
Det jeg mangler er, hvad er lige det navn der sættes lig med: "void
(*PF)()" ..? Det er der ikke... Det giver ikke mening (for en hvis Borland
Pascal nørd anyway)
at skrive "typedef void (*PF)()" hvis ikke man erklærer et navn værende af
den type (fx: "typedef void(*PF)() min_funktions_type")?
Et (stort) spørgsmåltegn,
Regards
Thomas Schulz
| |
Igor V. Rafienko (19-04-2001)
| Kommentar Fra : Igor V. Rafienko |
Dato : 19-04-01 13:49 |
|
* Thomas Schulz
[snip]
> typedef void (*PF)();
'PF' blir et annet navn for typen "void (*)()" (mao. "pointer to
function taking no arguments and returning void").
> PF edit_ops[] = {&cut, &paste, ©, &search};
> PF file_ops[] = {&open, &append, &close, &write};
> PF* button2 = edit_ops;
> PF* button3 = file_ops;
> Og så står der, at man fx kan kalde en funktion således
> "button2[2];"
Ehh... kanskje "button2( 2 )"?
> Det meste af ovenstående er egentligt logisk nok, der initialiseres
> et array of funktions pointere.. Men.. Hvad er det for en typedef
> deklaration!?!
typedef lager en alias for en eksisterende type (jeg kan vedde ganske
mye penger på at det står i den samme boken :) ).
> Tidligere i bogen er "typedef" beskrevet som bruges som følgende:
> "typedef long int32". Det er jo logisk nok. Det lader til at typedef
> fungerer sådan her: navn__da-der-er-mellemrum-samme-type-som__navn
> (bare læst omvendt :).
Situasjonen over er den samme -- man har en deklarasjon:
void (*PF)();
som deklarerer 'PF' til å være en funksjonspeker, og dersom man setter
typedef foran, blir 'PF' et annet navn (alias) for denne typen (nemlig
funksjonspeker):
typedef void (*PF)();
Det som jeg tror[tm] er litt forvirrende er syntaksen på
funksjonspekerdeklarasjonen:
<return-type> (*<pointer name>)( <argument list> );
fx.:
char* (*flabba)( const char* );
eller (som en bekjent av meg sa "en sadistjævel skrev det"):
void (*signal (int sig, void (*disp)(int)))(int);
Den siste deklarasjonen blir _mye_ klarere dersom man bruker typedef
for å lage seg bedre navn:
typedef void (*pfunc)( int );
pfunc signal( int sig, pfunc new_handler );
signal er en funksjon som tar 2 argumenter og returnerer en peker til
en funksjon. De to argumentene er en int og en peker til en funksjon.
> Det jeg mangler er, hvad er lige det navn der sættes lig med: "void
> (*PF)()" ..? Det er der ikke... Det giver ikke mening (for en hvis Borland
> Pascal nørd anyway)
$ cdecl
Type `help' or `?' for help
cdecl> explain void (*foo)()
declare foo as pointer to function returning void
cdecl>
putter man 'typedef' foran, blir "foo" et annet navn for typen
"pointer to function returning void".
> at skrive "typedef void (*PF)()" hvis ikke man erklærer et navn værende af
> den type (fx: "typedef void(*PF)() min_funktions_type")?
Som en tommelfingerregel: typedef kan stå foran en lovlig
deklarasjon/definisjon og det som ellers ville ha vært en variabel av
en bestemt type vil bli en alias for den samme typen:
int x; // declare/define 'x' of type 'int'
typedef int y; // make 'y' alias for type 'int'
void *foo; // declare/define 'foo' as pointer to void
typedef void *bar; // make 'foo' an alias for 'void*'
void (*zot)(); // declare/define 'zot' as pointer to function
// taking no arguments and returning void
typedef void (*qux)(); // make 'qux' an alias for type 'pointer to
// function taking no arguments and returning
// void
Alt dette står i TC++PL (det er jeg temmelig sikker på).
ivr
--
The only "intuitive" interface is the nipple. After that, it's all learned.
(Bruce Ediger, bediger@teal.csn.org, in comp.os.linux.misc, on X interfaces.)
| |
Torsten Iversen (19-04-2001)
| Kommentar Fra : Torsten Iversen |
Dato : 19-04-01 16:30 |
|
In article <xjvzodd3via.fsf@fjorir.ifi.uio.no>, Igor V. Rafienko wrote:
>* Thomas Schulz
>
>[snip]
>
>
>> typedef void (*PF)();
>
>
>'PF' blir et annet navn for typen "void (*)()" (mao. "pointer to
>function taking no arguments and returning void").
^^
>> PF edit_ops[] = {&cut, &paste, ©, &search};
>> PF* button2 = edit_ops;
>> Og så står der, at man fx kan kalde en funktion således
>> "button2[2];"
>
>
>Ehh... kanskje "button2( 2 )"?
>
Jeg læser det som om at button2 er en pointer til en pointer til en
funktion, der returnerer void og tager void.
button2 peger altså på starten af et array af pointere til funktioner, der
tager void og returnerer void. Derfor ville jeg kalde button2[2] sådan
her:
(*button2[2])();
[] derefererer pointeren button2 på offset 2, og * derefererer den pointer
til typen PF, som er gemt på position 2 i arrayet d.v.s. funktionen
copy. copy en funktion, der tager void - derfor parenteserne i
slutningen af udtrykket (egentlig styret af pointertypen, men den svarer
naturligvis til typen for copy). Der er parentes om *button2[2] for at
* operatoren skal virke på PF pointeren button2[2] i stedet for
returværdien fra kaldet.
Torsten
| |
Thomas Schulz (19-04-2001)
| Kommentar Fra : Thomas Schulz |
Dato : 19-04-01 19:51 |
|
> her:
>
> (*button2[2])();
Der står altså
"button2[2]();"
Men jeg mener (håber) også at have læst, at pointere til funktioner ikke
behøver at blive derefereret når man kalder dem?
Jeg behøver i hvert fald ikke skrive "&" foran for at tage sætte en
"funtion_pointer" = "&adresse_taget_fra_pointer_til_funktion", der kan jeg
bare skrive
"funtion_pointer" = "adresse_taget_fra_pointer_til_funktion". Det sidste
står på side 156 (7.7).
Thomas
| |
Thomas Schulz (19-04-2001)
| Kommentar Fra : Thomas Schulz |
Dato : 19-04-01 22:00 |
|
> Men jeg mener (håber) også at have læst, at pointere til funktioner ikke
> behøver at blive derefereret når man kalder dem?
> "funtion_pointer" = "adresse_taget_fra_pointer_til_funktion". Det sidste
> står på side 156 (7.7).
Og på samme side står også, at man kan undlåde at dereferer funktions
pointere.
Det var nok også det, du fra starten i virkeligheden mente (jeg misforstod
bare), du dereferer funktions pointere bare modsat Bjarne :).
mvh.
Thomas
| |
Torsten Iversen (21-04-2001)
| Kommentar Fra : Torsten Iversen |
Dato : 21-04-01 12:00 |
|
In article <9bncso$nte$1@news.inet.tele.dk>, Thomas Schulz wrote:
>> her:
>>
>> (*button2[2])();
>
>
>Der står altså
>"button2[2]();"
>
>
>Men jeg mener (håber) også at have læst, at pointere til funktioner ikke
>behøver at blive derefereret når man kalder dem?
Korrekt. Funktioner giver ikke mening som objekter, så det er ikke
nødvendigt at bruge addresse operatoren, når de assignes til en pointer,
ligesom det heller ikke er nødvendigt at dereferere dem, da det ikke giver
mening at bruge () på en pointer.
Jeg har bare vænnet mig til at bruge & og *, fordi det virker mest
logisk.
Torsten
| |
Igor V. Rafienko (21-04-2001)
| Kommentar Fra : Igor V. Rafienko |
Dato : 21-04-01 15:32 |
|
* Torsten Iversen
[snip]
> Funktioner giver ikke mening som objekter,
I C-familien, så... Funksjoner kan godt være objekter på lik linje med
de mer "vanlige" objekter. De kan godt skapes, ha attributter og
metoder tilknyttet dem, osv.
> så det er ikke nødvendigt at bruge addresse operatoren, når de
> assignes til en pointer,
Jovisst er det nødvendig (hint: member-functions).
[snip]
ivr
--
The only "intuitive" interface is the nipple. After that, it's all learned.
(Bruce Ediger, bediger@teal.csn.org, in comp.os.linux.misc, on X interfaces.)
| |
Torsten Iversen (21-04-2001)
| Kommentar Fra : Torsten Iversen |
Dato : 21-04-01 16:43 |
|
In article <xjvsnj2fhmw.fsf@gjallarhorn.ifi.uio.no>, Igor V. Rafienko wrote:
>* Torsten Iversen
>
>[snip]
>
>> Funktioner giver ikke mening som objekter,
>
>
>I C-familien, så... Funksjoner kan godt være objekter på lik linje med
>de mer "vanlige" objekter. De kan godt skapes, ha attributter og
>metoder tilknyttet dem, osv.
>
Kan du give et lille eksempel. Jeg er ikke sikker på at jeg forstår.
Jeg forstår en funktion (objekt) som den klump hukommelse, der bliver
brugt til at gemme instruktioner fra en funktionsdefinition. At kunne
manipulere den, har jeg ikke kendskab til at man kan i C++.
>
>> så det er ikke nødvendigt at bruge addresse operatoren, når de
>> assignes til en pointer,
>
>
>Jovisst er det nødvendig (hint: member-functions).
>
Tænker du på pointere til memberfunktioner? De er ikke
funktionspointere. Spørgsmålet drejede sig om funktionspointere.
I øvrigt nyt for mig (member pointere). Vil det sige, at det er forkert at
bruge &, hvis man vil have en rigtig pointer til en member funktion (jeg
er godt klar over, at det er uklogt at tage addreseen på en memberfunktion
og assigne den til en almindelig funktionspointer, fordi funktionen tager
et skjult this argument - som svjv ikke er standardiseret -, men spørger
af nysgerrighed).
Torsten
| |
Torsten Iversen (21-04-2001)
| Kommentar Fra : Torsten Iversen |
Dato : 21-04-01 17:06 |
|
In article <slrn9e3ajf.nfs.torsten@mega.cs.auc.dk>, Torsten Iversen wrote:
>
>I øvrigt nyt for mig (member pointere). Vil det sige, at det er forkert at
>bruge &, hvis man vil have en rigtig pointer til en member funktion (jeg
>er godt klar over, at det er uklogt at tage addreseen på en memberfunktion
>og assigne den til en almindelig funktionspointer, fordi funktionen tager
>et skjult this argument - som svjv ikke er standardiseret -, men spørger
>af nysgerrighed).
>
>Torsten
Hmm. Det var vist noget smuds, jeg kom ud i her. Man kan sikkert slet ikke
regne med noget som helst, hvis man assigner en member funktion til en
funktionspointer. Der ser i hvert fald ikke ud til at stå noget om det i
Bjarnebogen third edition.
Torsten
| |
Igor V. Rafienko (22-04-2001)
| Kommentar Fra : Igor V. Rafienko |
Dato : 22-04-01 14:29 |
|
* Torsten Iversen
[snip]
> > I C-familien, så... Funksjoner kan godt være objekter på lik linje
> > med de mer "vanlige" objekter. De kan godt skapes, ha attributter
> > og metoder tilknyttet dem, osv.
>
> Kan du give et lille eksempel. Jeg er ikke sikker på at jeg forstår.
Ad det å skape objekter -- lambda functions og closures.
Ad det med attributter -- det som jeg kommer på i farten er
dokumentasjonsteksten:
>>> def foo():
.... """ This function does foo """
.... return 1 + 2
....
>>> dir( foo )
['__doc__', '__name__', 'func_code', 'func_defaults', 'func_doc', 'func_globals', 'func_name
']
>>> foo.__doc__
' This function does foo '
>>>
(som du sikkert ser, har foo flere attributter enn bare doc string
(__doc__)).
Metoder tilknyttet en funksjon kan fx. være det å ekstrahere
informasjon om funksjonen og/eller dens omgivelse. Dessverre er ikke
dette mulig i C++, selv om noen av mulighetene er ganske nyttige (fx.
automatisk identifikasjon av det stedet i koden hvor en
logg/feilmelding kommer ifra (utrolig nyttig å få vite at metoden bar
i modullen zot feilet i rutine qux på linje 463):
[quote]
------------------------------
DEBUG message from ('127.0.0.1', 4860):
File: /home/igorr/mip/malib/kernel/kernel.py
Function: storeXML, line: 1004, time: 23:14:58
kernel.storexml started
------------------------------
[/quote]
Informasjonen om filen, funksjonen og linjenummeret er ekstrahert
nettopp ved å utnytte slike funksjonsattributter.
> Jeg forstår en funktion (objekt) som den klump hukommelse, der
> bliver brugt til at gemme instruktioner fra en funktionsdefinition.
> At kunne manipulere den, har jeg ikke kendskab til at man kan i C++.
Det kan man ikke. Vel, ikke portabelt. En bekjent av meg gjorde dette
for moro skyld på en MIPS R4000: man lager en liten kodesnutt, der man
passer på allokere hukommelse riktig (memalign), gjør en strcpy() fra
en string literal inn in denne hukommelseklumpen der tekstkonstanten
inneholder litt kode (han tok en assembly snutt og oversatt denne til
maskinkode), så typecast'er man denne hukommelsesklumpen til en
funksjonspeker og kaller denne. Fungerte som en drøm :) (kids, don't
try this at home :) ). Veldig interessant for å illustrere hvor nærme
maskinen man sitter i C, men ellers ganske ubrukelig.
[snip]
> >Jovisst er det nødvendig (hint: member-functions).
>
> Tænker du på pointere til memberfunktioner? De er ikke
> funktionspointere. Spørgsmålet drejede sig om funktionspointere.
Jeg oppfatter pointer to member function og pointer to function som 2
like ting (jada, standarden kaller dem for forskjellige, men imvho, er
det snakk om den samme tingen i begge tilfeller -- man har en funksjon
og man refererer til den vha. en peker).
Det som er smule irriterende er at standarden _krever_ & for member
functions, men ikke for vanlige funksjoner. IMVHO er dette lite
konsistent.
> I øvrigt nyt for mig (member pointere). Vil det sige, at det er
> forkert at bruge &, hvis man vil have en rigtig pointer til en
> member funktion
Nå er jeg ikke helt med. Man _må_ bruke & for å lage seg en pointer to
member (5.3.1, p 3).
> (jeg er godt klar over, at det er uklogt at tage addreseen på en
> memberfunktion og assigne den til en almindelig funktionspointer,
Det er ikke lov (dvs. konverteringen er ikke garantert å fungere), da
det ikke finnes en portabel måte å konvertere en "void (A::*)()" til
en "void (*)()" eller en "void*".
[snip]
ivr
--
The only "intuitive" interface is the nipple. After that, it's all learned.
(Bruce Ediger, bediger@teal.csn.org, in comp.os.linux.misc, on X interfaces.)
| |
Kent Friis (22-04-2001)
| Kommentar Fra : Kent Friis |
Dato : 22-04-01 15:07 |
|
Den 22 Apr 2001 15:28:58 +0200 skrev Igor V. Rafienko:
>Det kan man ikke. Vel, ikke portabelt. En bekjent av meg gjorde dette
>for moro skyld på en MIPS R4000: man lager en liten kodesnutt, der man
>passer på allokere hukommelse riktig (memalign), gjør en strcpy() fra
>en string literal inn in denne hukommelseklumpen der tekstkonstanten
>inneholder litt kode (han tok en assembly snutt og oversatt denne til
>maskinkode), så typecast'er man denne hukommelsesklumpen til en
>funksjonspeker og kaller denne. Fungerte som en drøm :) (kids, don't
>try this at home :) ). Veldig interessant for å illustrere hvor nærme
>maskinen man sitter i C, men ellers ganske ubrukelig.
Det skulle være lidt nemmere på x86-arkitekturen, da denne er ligeglad
med alignment. Efter sigende skulle følgende være nok til at sætte
en Pentium-processor ud af spillet, selvom compileren giver en
warning...
int main = 0xC8C70FF0; /* F0 0F C7 C8 */
(Programmet compilerer med GCC, men linux har for vane at lave noget
hokus-pokus, så BUG'en ikke virker, så jeg har ikke kunnet kontrollere
at det rent faktisk virker).
Mvh
Kent
--
http://www.celebrityshine.com/~kfr - sidste billede: planets.png
| |
Ulrik Magnusson (22-04-2001)
| Kommentar Fra : Ulrik Magnusson |
Dato : 22-04-01 18:06 |
|
Torsten Iversen wrote:
> Jeg forstår en funktion (objekt) som den klump hukommelse, der bliver
> brugt til at gemme instruktioner fra en funktionsdefinition. At kunne
> manipulere den, har jeg ikke kendskab til at man kan i C++.
Her er et fuldstændigt ubrugeligt eksempel, der virker med djgpp (i hvert
fald den version, jeg har). Man skulle tro, at f() altid udskriver 'a', men
man kan jo være en smule kreativ:
void f( )
{
char c = 'a';
cout << c << endl;
}
int main()
{
char* pf = (char*)&f;
cout << *(pf+9) << endl; //udskriver "c" variablen i f() - dvs 'a'
f(); // udskriver 'a'
*(pf+9) = 'b';// ændrer "c" variablen i f() til 'b'
f(); //udskriver 'b'
return 0;
}
Ulrik Magnusson
--
"hvorfor er det stadig tilladt at høre klassisk musik ?"
'Mickey', dk.politik.indvandring
Visit my home page: http://www.geocities.com/ulrikm
| |
Torsten Iversen (22-04-2001)
| Kommentar Fra : Torsten Iversen |
Dato : 22-04-01 19:52 |
|
In article <3AE30F8D.5BDE58A1@yahoo.com>, Ulrik Magnusson wrote:
>Torsten Iversen wrote:
>
>> Jeg forstår en funktion (objekt) som den klump hukommelse, der bliver
>> brugt til at gemme instruktioner fra en funktionsdefinition. At kunne
>> manipulere den, har jeg ikke kendskab til at man kan i C++.
>
>Her er et fuldstændigt ubrugeligt eksempel, der virker med djgpp (i hvert
>fald den version, jeg har). Man skulle tro, at f() altid udskriver 'a', men
>man kan jo være en smule kreativ:
>
>void f( )
>{
> char c = 'a';
> cout << c << endl;
>}
>int main()
>{
> char* pf = (char*)&f;
> cout << *(pf+9) << endl; //udskriver "c" variablen i f() - dvs 'a'
> f(); // udskriver 'a'
> *(pf+9) = 'b';// ændrer "c" variablen i f() til 'b'
> f(); //udskriver 'b'
> return 0;
>}
>
>Ulrik Magnusson
>
>--
>"hvorfor er det stadig tilladt at høre klassisk musik ?"
> 'Mickey', dk.politik.indvandring
>Visit my home page: http://www.geocities.com/ulrikm
>
>
Når jeg skriver at man ikke "kan i C++" mener jeg, at det ikke er en
del af C++ semantikken. At det operativsystem, den compiler, den
hardwareplatform og de flag, du har kompileret med, muliggør at
manipulere en funktion, viser ikke noget om, at man kan gøre det i
C++. Du har foretaget en skrivning, som tilfældigvis under alle de
betingelser som er til stede ændrer funktionen.
Torsten
| |
Ulrik Magnusson (22-04-2001)
| Kommentar Fra : Ulrik Magnusson |
Dato : 22-04-01 20:36 |
|
Torsten Iversen wrote:
> Når jeg skriver at man ikke "kan i C++" mener jeg, at det ikke er en
> del af C++ semantikken. At det operativsystem, den compiler, den
> hardwareplatform og de flag, du har kompileret med, muliggør at
> manipulere en funktion, viser ikke noget om, at man kan gøre det i
> C++. Du har foretaget en skrivning, som tilfældigvis under alle de
> betingelser som er til stede ændrer funktionen.
Du er nok ikke ude efter følgende:
char* ff = (char*)f;
*ff = 0;
Hvilket ændrer funktionen (så meget, at den ikke kan bruges). Men hvad
så med denne:
char* f()
{
static char c = 'a';
cout << c << endl;
return &c;
}
int main()
{
char* c = f();
*c = 'b';
f();
return 0;
}
Kan man overhovedet sige, at "c" er en del af funktionen f(), når den er
erklæret "static"?
Ulrik Magnusson
--
"What a surprise! A look of terminal shock in your eyes.
Now things are really what they seem."
Pink Floyd - "Sheep", Animals 1977
Visit my home page: http://www.geocities.com/ulrikm
| |
Torsten Iversen (22-04-2001)
| Kommentar Fra : Torsten Iversen |
Dato : 22-04-01 21:23 |
|
In article <3AE33295.B83F09B2@yahoo.com>, Ulrik Magnusson wrote:
>
>Du er nok ikke ude efter følgende:
>
>char* ff = (char*)f;
>*ff = 0;
>
Jeg er ikke ude efter noget særligt. Diskuterer bare emnet for sjovs
skyld.
>Hvilket ændrer funktionen (så meget, at den ikke kan bruges). Men hvad
>så med denne:
>
>char* f()
>{
> static char c = 'a';
> cout << c << endl;
> return &c;
>}
>int main()
>{
> char* c = f();
> *c = 'b';
> f();
> return 0;
>}
>
>Kan man overhovedet sige, at "c" er en del af funktionen f(), når den er
>erklæret "static"?
>
Nej. c er navnet på en datadefinition. Ved at modificere c, laver man
en ændring i data, som er veldefineret i sproget C og skal understøttes
af en korrekt implementation af sproget. I eksemplet i dit tidligere
indlæg, har du modificeret en instruktion, som tilfældigvis har sit
argument på en 8-bit aligned addresse i kodesegmentet.
Fra dit oprindelige indlæg:
>void f( )
>{
> char c = 'a';
> cout << c << endl;
>}
>int main()
>{
> char* pf = (char*)&f;
> cout << *(pf+9) << endl; //udskriver "c" variablen i f() - dvs 'a'
Nej. Udskriver værdien af en byte i kodesegmentet, som indeholder et
argument til en instruktion. Hvis din compiler/HW f.eks. brugte en 16
bit store instruktion med 4 bit opcode og 12 bit værdi, ville det ikke
virke.
Ejheller ville det virke, hvis instruktionen hentede værdien fra en
addresse med værdien 'a' og derefter tilskrev denne værdi til c.
> f(); // udskriver 'a'
> *(pf+9) = 'b';// ændrer "c" variablen i f() til 'b'
Igen er det ikke en ændring af variablen, men derimod en ændring
af den instruktion, som bruges til at tilskrive en værdi til den
automatiske variabel c i f().
>
> f(); //udskriver 'b'
> return 0;
>}
Torsten
| |
Ulrik Magnusson (22-04-2001)
| Kommentar Fra : Ulrik Magnusson |
Dato : 22-04-01 21:45 |
|
Torsten Iversen wrote:
> In article <3AE33295.B83F09B2@yahoo.com>, Ulrik Magnusson wrote:
> >Kan man overhovedet sige, at "c" er en del af funktionen f(), når den er
> >erklæret "static"?
> Nej. c er navnet på en datadefinition. Ved at modificere c, laver man
> en ændring i data, som er veldefineret i sproget C og skal understøttes
> af en korrekt implementation af sproget.
Ok - jeg synes bare ikke denne adskillelse af instruktioner og data er
åbenbar i ordet "funktion". Jeg tænker på en "funktion" som kroppen af
denne. Man kan vel også sige at "buffer-overflow" netop bruger denne
svaghed - at man kan ændre funktioner.
Ulrik Magnusson
--
"What a surprise! A look of terminal shock in your eyes.
Now things are really what they seem."
Pink Floyd - "Sheep", Animals 1977
Visit my home page: http://www.geocities.com/ulrikm
| |
Richard Flamsholt (19-04-2001)
| Kommentar Fra : Richard Flamsholt |
Dato : 19-04-01 22:18 |
|
torsten@mega.cs.auc.dk (Torsten Iversen) skrev:
>(*button2[2])();
Derefereringen er korrekt, men overflødig. Jeg ville oftest bruge den
kortere og mere læsevenlige udgave:
button2[2]();
button[2] er ganske vist en pointer til en funktion, men en sådan kan
bruges direkte til et funktionskald. Man behøver ikke dereferere og får
dermed lidt simplere kode uden det ekstra sæt forvirrende parenteser.
Arh, ok, lad mig omformulere: hvis éns kode kun indeholder enkelte af
den slags udtryk og skal kunne læses af såvel grønne som garvede, så sæt
bare den ekstra (*...) på. I kode fyldt med funktionspointere vil den
korte udgave derimod øge læsbarheden markant.
--
Richard Flamsholt
richard@flamsholt.dk - www.richard.flamsholt.dk
| |
Igor V. Rafienko (20-04-2001)
| Kommentar Fra : Igor V. Rafienko |
Dato : 20-04-01 12:20 |
|
* Torsten Iversen
> >> PF edit_ops[] = {&cut, &paste, ©, &search};
> >> PF* button2 = edit_ops;
> >> Og så står der, at man fx kan kalde en funktion således
> >> "button2[2];"
> >
> >Ehh... kanskje "button2( 2 )"?
>
> Jeg læser det som om at button2 er en pointer til en pointer til en
> funktion, der returnerer void og tager void.
Jeg _lover_ å pelle meg til øyelege/optiker. Beklager, jeg sløvet. Men
man er fremdeles nødt til å ha () etterpå, altså "button2[2]" vil gi
en funksjonspeker, men du må fremdeles kalle funksjonen som denne
peker på.
> button2 peger altså på starten af et array af pointere til funktioner, der
> tager void og returnerer void. Derfor ville jeg kalde button2[2] sådan
> her:
>
> (*button2[2])();
button2[2]();
er et alternativ (de-ref er implisitt for funksjonspekere). Det står
faktisk også på side 157 i TC++PL3ed.
ivr
--
The only "intuitive" interface is the nipple. After that, it's all learned.
(Bruce Ediger, bediger@teal.csn.org, in comp.os.linux.misc, on X interfaces.)
| |
Thomas Schulz (19-04-2001)
| Kommentar Fra : Thomas Schulz |
Dato : 19-04-01 21:08 |
|
> > typedef void (*PF)();
> 'PF' blir et annet navn for typen "void (*)()" (mao. "pointer to
> function taking no arguments and returning void").
Mmm
> typedef lager en alias for en eksisterende type (jeg kan vedde ganske
> mye penger på at det står i den samme boken :) ).
Altså, jeg kan godt se at "alis" er en mere korrekt beskrivelse af typedef,
men jeg slog op under indeks og side 84, og der står ikke lige præcist, at
det hedder et alis <>. Anyway, den brug af typedef, som jeg har/haft
problemer med her, står altså ikke beskrevet der.
> som deklarerer 'PF' til å være en funksjonspeker, og dersom man setter
> typedef foran, blir 'PF' et annet navn (alias) for denne typen (nemlig
> funksjonspeker):
>
> typedef void (*PF)();
Det står overhovedet ikke i nogen, det eneste man får, er eksempler derpå,
man får ingen forklaring
(jeg må antage at grunden til, at det ikke er nævnt, er at man antages at
kunne regne det ud <g> :).
> Ehh... kanskje "button2( 2 )"?
For at være helt præcist (sidder og kigger i bogen)
"button2[2]();"
> Det som jeg tror[tm] er litt forvirrende er syntaksen på
> funksjonspekerdeklarasjonen:
> <return-type> (*<pointer name>)( <argument list> );
> fx.:
> char* (*flabba)( const char* );
Syntaksen er lidt forvirrende, men jeg har nu været i stand til at holde
tungen lige og ikke blive hægtet af af syntaksen.
Nu hvor jeg saf og læste det du skrev, blev jeg faktisk hægtet af lige her,
det tog mig 20 minutter at (gen)fatte igen.
> eller (som en bekjent av meg sa "en sadistjævel skrev det"):
> void (*signal (int sig, void (*disp)(int)))(int);
>
> Den siste deklarasjonen blir _mye_ klarere dersom man bruker typedef
> for å lage seg bedre navn:
Man kan også dele den op sådan her:
void (
*signal (
int sig, void (
*disp)(int)
)
)(int);
Omend din metode lader til at være noget bedre :).
> typedef void (*pfunc)( int );
>
> pfunc signal( int sig, pfunc new_handler );
> signal er en funksjon som tar 2 argumenter og returnerer en peker til
> en funksjon. De to argumentene er en int og en peker til en funksjon.
> pfunc signal( int sig, pfunc new_handler );
OK, desto mere jeg bliver hjernevas.. ehh.. tænker efter <smil>, desto mere
mening giver det, jeg forstår det godt (jeg er dog rimeligt tæt på at bide
min tunge af :).
> > Pascal nørd anyway)
>
> $ cdecl
> Type `help' or `?' for help
> cdecl> explain void (*foo)()
> declare foo as pointer to function returning void
> cdecl>
>
> putter man 'typedef' foran, blir "foo" et annet navn for typen
> "pointer to function returning void".
Jeg må vist se at skaffe mig en C++ compiler + IDE. Det Emacs (har prøvet
den til Windows.. Bvadr! :) mv. tjavs blev for meget for en Windows-dummie
som mig. Jeg har dog efterhånden fået kigget på nogle gratis nogle (til
Windows). Jeg har ganske vist også C++ Builder 3 standard, den installerer
jeg en af dagene.
> > at skrive "typedef void (*PF)()" hvis ikke man erklærer et navn værende
af
> > den type (fx: "typedef void(*PF)() min_funktions_type")?
>
> Som en tommelfingerregel: typedef kan stå foran en lovlig
> deklarasjon/definisjon og det som ellers ville ha vært en variabel av
> en bestemt type vil bli en alias for den samme typen:
Mange tak for forklaringen (som man endda kan huske), eksemplet giver megen
mere mening nu. Jeg havde spekuleret om det var noget med store bogstaver
(idet alle "typedef" eksemplerne på den side i bogen brugte store bogstaver
for "type|variabel" navnene) <g>.
> int x; // declare/define 'x' of type 'int'
> typedef int y; // make 'y' alias for type 'int'
>
> void *foo; // declare/define 'foo' as pointer to void
> typedef void *bar; // make 'foo' an alias for 'void*'
>
> void (*zot)(); // declare/define 'zot' as pointer to function
> // taking no arguments and returning void
>
> typedef void (*qux)(); // make 'qux' an alias for type 'pointer to
> // function taking no arguments and returning
> // void
>
Igen mange tak, nu har jeg fået banket det ind.
> Alt dette står i TC++PL (det er jeg temmelig sikker på).
Turbo C++ ? Mmm..
Tænke sig, det tog mig godt og vel en time at skrive et svar :), du giver
mig altid lidt at tænke over :).
Regards
Thomas Schulz
| |
Kent Friis (19-04-2001)
| Kommentar Fra : Kent Friis |
Dato : 19-04-01 21:15 |
|
Den Thu, 19 Apr 2001 22:07:38 +0200 skrev Thomas Schulz:
>
>> Alt dette står i TC++PL (det er jeg temmelig sikker på).
>Turbo C++ ? Mmm..
Mon ikke det er "The C++ Programming Language" der omtales?
Mvh
Kent
--
http://www.celebrityshine.com/~kfr - sidste billede: planets.png
| |
Thomas Schulz (19-04-2001)
| Kommentar Fra : Thomas Schulz |
Dato : 19-04-01 21:55 |
|
> Mon ikke det er "The C++ Programming Language" der omtales?
Jo.. Nu du siger det. Det er bare fordi jeg mente at have hørt PL før i
omtale i forbindelse med noget C++ compiler, så jeg tænkte det var en eller
anden tilføjelse eller akronym, som jeg ikke kendte til :)
mvh
Thomas
| |
|
|