PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C: array als rückgabe wert eine funktion



Asraniel
06-04-2005, 16:27
ich habe Follgendes problem:
ich möchte das eine funktion ein char array, dessen Grösse ich nicht kenne, zurückgibt.
ich habe also vollgendes programm:



char *testArray(){
char *a = "asdf";
return a;
}

main() {
char *b = testArray();
printf("%s",b);
}

wenn ich nun aber diesen code schreibe, und das muss ich:



char *testArray(){
char *a = {'a','s','d','f','\0'};
return a;
}

main() {
char *b = testArray();
printf("%s",b);
}


habe ich zum einen diese compile warnings:


hello.c: In function `testArray':
hello.c:55: warning: initialization makes pointer from integer without a cast
hello.c:55: warning: excess elements in scalar initializer
hello.c:55: warning: (near initialization for `a')
hello.c:55: warning: excess elements in scalar initializer
hello.c:55: warning: (near initialization for `a')
hello.c:55: warning: excess elements in scalar initializer
hello.c:55: warning: (near initialization for `a')


und beim ausführen ein Segmentation fault. Warum? wie kann ich machen das es funktioniert?

Boron
06-04-2005, 16:35
Das hier lesen: http://www.mrunix.de/forums/showthread.php?t=38555

Und zum Segfault:
du legst den String ja lokal in der Funktion an.
Beim Verlassen der Funktion wird der String gelöscht.
Da du den String aber außerhalb der Funktion weiter verwenden willst zeigt "b" in einen Speicherbereich, wo offiziell nichts ist.
Der Segfault macht das unmissverständlich klar.

Asraniel
06-04-2005, 16:41
danke, mein problem ist nur, dass das erste beispiel funktioniert und das zweite nicht, nur dass beide für mich das genau gleiche ist (bin java coder ;-) )

edit: lese grad die FAQ die dort gelinkt wurde, verstehe schon etwas mehr. nur dass ich nicht weiss wie ich es denn nun machen soll. Weil das hier:




char *testArray(){
char a[] = {'a','s','d','f','\0'};
return &a;
}

main() {
char *b = testArray();
printf("%s",b);
}


geht auch nich, follgende errors kommen beim kompilieren


hello.c: In function `testArray':
hello.c:56: warning: return from incompatible pointer type
hello.c:56: warning: function returns address of local variabl

edit2: ohne das & beim return gehts auch nicht wesentlich besser

RHBaum
06-04-2005, 16:49
naja, du gibts nen zeiger aufn array zurueck, was nach beendigung der funktion im nirvana verschwindet .....

gibt paar regeln, an die man sich halten sollt. ....
eine iss zum beispiel, das man speicher immer im gleichen block allocieren und wieder deallocieren sollte .... oder im Konstructor / Destructor ner klasse ...

Willst unbedingt den String als rueckgabewert, dann solltes ne klasse verwenden ..... (falls c++ verwendest)

C-Funktionen gaengiger API's geben nie den allocierten speicher als Rueckgabewert zrueck (sei denn es ist eine spezialisierte funktion nur zum allocieren von gewissen spiecher) sondern schreiben auf vorhandenen Bereichen ......

mesit werden die funktionen, wenn sie viel speicher beschreiben koennten, in 2 modis betrieben .....

int writeArray(int * anz,char * buffer);

einmal setzt buffer (den zeiger) auf null, so dass deine funktion weiss dass sie nich auf den speicher schreiben soll ... dan gibt sie die benoetigte Groesse zurueck, in dem sie den an die sspeicherstelle von anz schreibt ....
und einmal gibst ihr nen reservierten zeiger, und in anz die Groesse des allociertern bereiches .... so das sie weis wie viel sie max schreiben kann ....

Hat den vorteil, das der benutze der funktionen sowohl statisch auf Geschwindigkeit, oder auch dynamisch auf verwendeten speicher optimieren kanne .....

1. version saehe so aus ...

const int MaxBufferSize = 1024;
int Anz = MaxBufferSize ;
char buffer[MaxBufferSize ]; // soll fuer alle anwendungsfaelle reichen ..... spart die kosten einer dynamischen allocation ....


ires = writeArray(&Anz ,buffer); // hier wird ins array nu geschrieben

oder version 2 .....

int anz = 0;

ires = writeArray(&Anz ,NULL); // statt NULL 0 nehmen falls nichdefiniert ...
// in Anz steht nu die benoetigte groesse
char * buffer = (char *) malloc(anz*sizeof(char));
ires = writeArray(&Anz ,buffer); // hier schreibt er nu wirklich ....

// nach dem anwenden loeschen ned vergessen

free(buffer);

Ciao ...

panzi
06-04-2005, 20:31
sizeof(char) ist AFAIK per definition 1.

Asraniel
06-04-2005, 21:26
RHBaum:
ich habe alles versucht, aber es geht irgendwie nicht!


void testArray(char *buffer){
buffer = "asdf";
}

main() {
char buffer[20];
testArray(&buffer);
printf("%s",buffer);
}

das sollte doch gehen? oder hab ich was nicht verstanden? ohne das & geht es auch nicht

panzi
06-04-2005, 21:41
RHBaum:
ich habe alles versucht, aber es geht irgendwie nicht!


void testArray(char *buffer){
buffer = "asdf";
}

main() {
char buffer[20];
testArray(&buffer);
printf("%s",buffer);
}

das sollte doch gehen? oder hab ich was nicht verstanden? ohne das & geht es auch nicht

Also das geht schon garnicht.
Das geht z.B., aber ACHTUNG, der String liegt da im .TEXT Block und ist somit read-only:

void get_string(const char ** buffer){
*buffer = "asdf";
}

int main() {
const char * str;
get_string( &buffer );
puts( string );
}

Oder das:


char * get_new_string() {
char * str = malloc( XXX );
if( str ) strncpy( str, XXX, XXX );
return str;
}

int main() {
char * str = get_new_string();

puts( str );

/* WICHTIG! */
free( str );
return 0;
}

Oder:


void get_string( char * buf, sitze_t size ) {
strncpy( buf, XXX, size );
}

int main() {
char buf[ XXX ];

get_string( buf, XXX );
puts( str );

return 0;
}

RHBaum
07-04-2005, 08:57
@panzi

sizeof(char) ist AFAIK per definition 1.
Mir ist keine Impl bekannt wo es nich so ist, aber sag niemals nie :-)
Zumal Dir sizeof in dem Fall keine kosten zur laufzeit beschert ... isses eigentlich egal :-) Stecks in die Kategorie Paranoia :-)

@Asraniel
Schau dir Strings noch mal genauer an ... und Zeiger. Erst wenn Dir selber klar iss, wass Du in deinem Beispiel genau tust, solltest mit anderen Sachen weitermachen ....
Grad wenn C Programmieren willst, muss Dir das tief ins Hirn eigebrannt sein ... und "Fehler" durfen nur noch vom Vertippern, bzw unachtsamkeiten herkommen, aber keine logischen Zweifel mehr sein :-) Sonst kommst in Teufels Kueche !

Nur als Tipp, man kann Zeiger kopieren, und man kann den Inhalt kopieren, auf den Zeiger zeigen, und es ist was total unterschiedliches :-)
Wenn du also Daten auf ein array kopieren willst, wird es mit dem kopieren eines einfachen datentypes nicht erledigt sein, sondern du musst Hilfsfunktionen zu rate ziehen ... memcpy, strcpy, strncpy ... etc sind solche Kandidaten ....

Ciao ...

peschmae
07-04-2005, 18:04
@panzi

Mir ist keine Impl bekannt wo es nich so ist, aber sag niemals nie :-)
Zumal Dir sizeof in dem Fall keine kosten zur laufzeit beschert ... isses eigentlich egal :-) Stecks in die Kategorie Paranoia :-)


Soviel ich weiss hat panzi recht - das Byte in C ist per Definition die Grösse von einem Char (und soviel ich weiss sogar diesen Weg rum definiert)

http://www.eskimo.com/~scs/C-faq/q7.8.html

MfG Peschmä

RHBaum
08-04-2005, 09:20
Im standard steht auch viel ... progge mal mit VC 6.0 ... iss das ueberhaupt C++ ? :-)

Hat nix mit dem char und byte zu tun ... ich propagier ja auch ned, dass ihrs machen sollt :p wie gesagt, es kostet nichts also lass ich es stehen ...

Da ich normal viel mit templates mache, sind typen bei mir eh oft relativ, also verwende ich sehr oft sizeof ... iss also eher nen reflex ...

Wieso muss ich mich dafuer eigentlich rechtfertigen ? :D Warum stosst ihr euch so an dem sizeof(char) ???

Ciao ...