/ Forside / Teknologi / Udvikling / C/C++ / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
C/C++
#NavnPoint
BertelBra.. 2425
pmbruun 695
Master_of.. 501
jdjespers.. 500
kyllekylle 500
Bech_bb 500
scootergr.. 300
gibson 300
molokyle 287
10  strarup 270
Funktioner der returnerer const
Fra : Jesper Gødvad


Dato : 26-05-01 11:08

Hej Alle.

Er der en der vil give et eksempel på forskellen mellem nedenstående
funktions erklæringer?
const int f( );
int f( );

mvh. jesper



 
 
Thomas Jespersen (26-05-2001)
Kommentar
Fra : Thomas Jespersen


Dato : 26-05-01 11:51

"Jesper Gødvad" <Xesper@goedvad.dk> writes:

> Er der en der vil give et eksempel på forskellen mellem nedenstående
> funktions erklæringer?
> const int f( );
> int f( );

Det betyder at den værdi du returnerer er konstant. Den giver ikke så
meget mening når du returnerer en værdi som i dit eksempel, men hvis
du f.eks. returnerer en pointer fortæller du den der kalder at den
ikke kan ændre på det der sendes tilbage:

const char* foo(void)
{
return "bar\n";
}

Jonas Meyer Rasmusse~ (30-05-2001)
Kommentar
Fra : Jonas Meyer Rasmusse~


Dato : 30-05-01 13:42

> const char* foo(void)
> {
> return "bar\n";
> }

Det som du returnerer her er rigtigtnok const, men det ændrer
altså ikke på det faktum at du har begået en klassisk fejl.

Du kan på ingen måde vide hvad pegeren peger på når funktionen
returnerer, den plads som bliver sat af til "bar\n", vil blive lagt på
stakken(som bliver frigivet efter funktionskaldet returnerer).
Det vil sige at du giver en peger til noget hukommelse der
ikke længere er reserveret.. pyyh

Jonas



Igor V. Rafienko (30-05-2001)
Kommentar
Fra : Igor V. Rafienko


Dato : 30-05-01 14:27

* Jonas Meyer Rasmussen

> > const char* foo(void)
> > {
> > return "bar\n";
> > }
>
> Det som du returnerer her er rigtigtnok const, men det ændrer
> altså ikke på det faktum at du har begået en klassisk fejl.


Nope, han hadde faktisk rett.


> Du kan på ingen måde vide hvad pegeren peger på når funktionen
> returnerer, den plads som bliver sat af til "bar\n", vil blive lagt
> på stakken(som bliver frigivet efter funktionskaldet returnerer).


Sludder:

[quote]

An ordinary string literal has type "array of n const char" and static
storage duration (3.7) ...

[/quote]

[quote]

All object which ... have static storage duration. The storage for
these objects shall last for the duration of the program.

[/quote]

Og selv om "bar\n" skulle ha blitt plassert på stacken, må det
objektet eksistere fremdeles så lenge programmet kjører. Og et lite
eksempel:


void
foo()
{
int mark1;
const char * const p = "foo\n";
int mark2;
char buf[] = "foo\n";
int mark3;

cout << (void*)(&mark1) << "\n";
cout << (void*)p << "\n";
cout << (void*)(&mark2) << "\n";
cout << (void*)buf << "\n";
cout << (void*)(&mark3) << "\n";
}

$ ./a.out
0xffbef2fc
0x286c0
0xffbef2f4
0xffbef2e8
0xffbef2e4
$

ser du forskjellen?


> Det vil sige at du giver en peger til noget hukommelse der ikke
> længere er reserveret.. pyyh


Nope.





ivr
--
Amy: Psst... look what life was like before genetic engeneering.
Leela: Those poor 20th century women...
-- Futurama, "Why must I be a Crustacean in love?"

Jonas Meyer Rasmusse~ (08-06-2001)
Kommentar
Fra : Jonas Meyer Rasmusse~


Dato : 08-06-01 14:52


"Igor V. Rafienko" <igorr@ifi.uio.no> wrote in message
news:xjvu2237yt3.fsf@vimur.ifi.uio.no...
[snip]
> Nope, han hadde faktisk rett.
>
> > Du kan på ingen måde vide hvad pegeren peger på når funktionen
> > returnerer, den plads som bliver sat af til "bar\n", vil blive lagt
> > på stakken(som bliver frigivet efter funktionskaldet returnerer).
>
>
> Sludder:
>
> [quote]
>
> An ordinary string literal has type "array of n const char" and static
> storage duration (3.7) ...
>
> [/quote]
>
> [quote]
>
> All object which ... have static storage duration. The storage for
> these objects shall last for the duration of the program.
>
> [/quote]

Okay, jeg var ikke klar over det at det fungerede således.
jeg tog desværre fejl, det er jeg ked af.

> Og selv om "bar\n" skulle ha blitt plassert på stacken, må det
> objektet eksistere fremdeles så lenge programmet kjører. Og et lite
> eksempel:

Det forstår jeg ikke
Hvis den ikke har statisk leve-tid så går den vel galt?
se her:

char* foo(){
char buff[] = "foo";
return buff;
}

void bar()
char* result;
result = foo()
char bleh[] = "baaaaaaaaaaaaaaar";
cout << result;
}

Dette vil vel ikke skrive foo ud, da der efter funktionskaldet returnerer
vil pladsen
blive frigivet... og da vi reserverer mere plads på stakken med bleh, så
vil det blive overskrevet.
??

> void
> foo()
> {
> int mark1;
> const char * const p = "foo\n";
> int mark2;
> char buf[] = "foo\n";
> int mark3;
>
> cout << (void*)(&mark1) << "\n";
> cout << (void*)p << "\n";
> cout << (void*)(&mark2) << "\n";
> cout << (void*)buf << "\n";
> cout << (void*)(&mark3) << "\n";
> }
>
> $ ./a.out
> 0xffbef2fc
> 0x286c0
> 0xffbef2f4
> 0xffbef2e8
> 0xffbef2e4
> $
>
> ser du forskjellen?
Ja, det er klart.
Men det illustrerer stadig ikke at det ville have virket hvis variablen ikke
var statisk...
du skriver jo det hele ud inde i funktionen, hvilket gør at alt på stakken
skal eksistere ?!?


Jonas



Igor V. Rafienko (08-06-2001)
Kommentar
Fra : Igor V. Rafienko


Dato : 08-06-01 16:14

* Jonas Meyer Rasmussen

[snip]

> > Og selv om "bar\n" skulle ha blitt plassert på stacken, må det
> > objektet eksistere fremdeles så lenge programmet kjører. Og et
> > lite eksempel:
>
> Det forstår jeg ikke
> Hvis den ikke har statisk leve-tid så går den vel galt?


Det er ingen korrelasjon mellom "statisk levetid" og "stack" (jeg
tror[tm] dette er årsaken til en liten misforståelse). Det er ofte
tilfellet at statiske data ikke plasseres på stack'en, men det må ikke
være slik. Tenk deg at statiske data blir plassert på stack'en like
før kallet på main. Det er en veldig uvanlig implementasjon, men det
kan definitivt realiseres slik.

Dersom et lokalt objekt har "static storage duration", kan man
referere til dette objektet gjennom hele programmets levetid. Hvor det
objektet ligger har strengt tatt ingen relevans (jeg har aldri
forstått hvorfor folk tok seg tiden og bryet med å finne det ut). Legg
merke til at det er _vesentlig_ stor forskjell mellom:

const char *foo = "flabba";

og

const char bar[] = "flabba";

I det første tilfellet peker foo på objektet "flabba". I det andre
tilfellet blir bar initialisert med en _kopi_ av objektet flabba.
_Derfor_ vil:

> se her:
>
> char* foo(){
> char buff[] = "foo";
> return buff;
> }

fungere _veldig_ dårlig.


> void bar()
> char* result;
> result = foo()
> char bleh[] = "baaaaaaaaaaaaaaar";
> cout << result;
> }
>
> Dette vil vel ikke skrive foo ud, da der efter funktionskaldet
> returnerer vil pladsen blive frigivet...


Helt korrekt.


> og da vi reserverer mere plads på stakken med bleh, så vil det blive
> overskrevet. ??


Som sagt 'buff' vil inneholde kopien av "foo". Og man returnerer
pekeren til denne kopien hvilken blir frigjort etter at
funksjonskallet på 'foo' er avsluttet.

I den opprinnelige meldingen så funksjonen slik ut:

const char*
foo()
{
return "foo";
}

og da er det ingen kopier på gang. Hadde denne blitt skrevet som

const char*
foo()
{
char buf[] = "foo";
return buf; // ERROR!
}

ville det ha vært feil.

[snip]


> > $ ./a.out
> > 0xffbef2fc
> > 0x286c0
^^^^^^^
[*]

> > 0xffbef2f4
> > 0xffbef2e8
> > 0xffbef2e4
> > $
> >
> > ser du forskjellen?
>
> Ja, det er klart.
> Men det illustrerer stadig ikke at det ville have virket hvis variablen ikke
> var statisk...


Det ville ikke ha virket, hadde variabelen ikke vært statisk
(misforstod jeg noe?). Det er 2 ting som er viktige her:

* typen til variabelen (spesielt array vs. pointer)
* og storage duration til innholdet til variabelen:


void
foo()
{
const char *foo = "flabba";
static char bar[] = "more flabba";
char zot[] = "no flabba";
}

Etter at funksjonskallet på 'foo' er avsluttet er det lov å refererer
til:

* foo (siden denne peker på et objekt med 'static storage duration')
* bar (siden objektet (array'en) har 'static storage duration')

Hvorvidt disse legges på stack'en, heap'en eller et eget segment
spiller _ingen_ rolle.


> du skriver jo det hele ud inde i funktionen, hvilket gør at alt på stakken
> skal eksistere ?!?


Jeg skulle bare poengere at objekter med "static storage duration"
blir plassert et annet sted (legg merke til hvordan adressen til det
som p peker på er forskjellig fra alle andre variable) enn lokale
variable. Høyst sannsynlig er det ikke stack'en. Men, som sagt, det
trenger ikke å være slik (tenk deg en implementasjon som ikke bruker
stack'en i det hele tatt -- _alle_ data legges på heap'en (slik er det
i noen programmeringsspråk og C kan definitivt implementeres på denne
måten)).

Snakket vi forbi hverandre?





ivr
--
Much of this software was user-friendly, meaning that it was intended
for users who did not know anything about computers, and furthermore
had absolutely no intention whatsoever of learning.
   -- A. S. Tanenbaum, "Modern Operating Systems, ch 1.2.4"

Jonas Meyer Rasmusse~ (11-06-2001)
Kommentar
Fra : Jonas Meyer Rasmusse~


Dato : 11-06-01 07:56

> Snakket vi forbi hverandre?

Nej, det tror jeg ikke, jeg er ihvertfald med på hvad du mener

Jeg var vist lidt forvirret om hvad forskellen på const char* og const
char[] var :)

Jonas



Igor V. Rafienko (11-06-2001)
Kommentar
Fra : Igor V. Rafienko


Dato : 11-06-01 14:50

* Jonas Meyer Rasmussen

> Jeg var vist lidt forvirret om hvad forskellen på const char* og const
> char[] var :)


Som sagt

"Expert C Programming: Deep C Secrets",
Peter van der Linden
ISBN 0-131-77429-8
SunSoft Press/Prentice Hall

Det er opptil flere kapitler som omhandler tema "pointers vs. arrays".
Og så er den underholdende å lese.





ivr
--
Amy: Psst... look what life was like before genetic engeneering.
Leela: Those poor 20th century women...
-- Futurama, "Why must I be a Crustacean in love?"

Jesper Gødvad (03-06-2001)
Kommentar
Fra : Jesper Gødvad


Dato : 03-06-01 02:18

> > Er der en der vil give et eksempel på forskellen mellem nedenstående
> > funktions erklæringer?
> > const int f( );
> > int f( );
>
> Det betyder at den værdi du returnerer er konstant. Den giver ikke så
> meget mening når du returnerer en værdi som i dit eksempel, men hvis
> du f.eks. returnerer en pointer fortæller du den der kalder at den
> ikke kan ændre på det der sendes tilbage:

Er det kun en ren 'dokumentationsmæssig' fordel eller er der et formål man
ikke kan opnå uden at returnere en const pointer?

Kunne jeg fx bruge det i det tilfælde jeg har en klasse, der i constructoren
altid fylder det samme i en container og
jeg derfor bare vil kopiere en default instance så brugeren selv kan
indsætte resten i containerklassen?. Tja, nu sidder jeg og tænker at det kan
man da sikkert uden const, så hvorfor lave en constpointer?

mvh. jesper



Per Abrahamsen (05-06-2001)
Kommentar
Fra : Per Abrahamsen


Dato : 05-06-01 17:31

"Jesper Gødvad" <Xesper@goedvad.dk> writes:

> Er det kun en ren 'dokumentationsmæssig' fordel eller er der et formål man
> ikke kan opnå uden at returnere en const pointer?

const char* foo ()
{
static const char data[] = "foo";
return data;
}

char* bar ()
{
static const char data[] = "foo";
return data;
}

c++ -c test.cpp
test.cpp: In function `char * bar()':
test.cpp:10: return to `char *' from `const char *' discards qualifiers

Søg
Reklame
Statistik
Spørgsmål : 177501
Tips : 31968
Nyheder : 719565
Indlæg : 6408522
Brugere : 218887

Månedens bedste
Årets bedste
Sidste års bedste