PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Pointer in C, Funktionsübergabeparameter problem



newc0mer
03-04-2006, 14:20
Oke. ich denke der topic sagt schon das wichtigste aus. hier der code:
Funktionsaufruf:

var = function(testvar, *argv[3]);
Argv ist ein Pointer und enhält einen String von 3 Zeichen, welcher beim Programmstart mitgegeben wurden.
Aufzurufende Funktion:

int function(int testvar, char program_parameter)
{
char foo[2]; // Variable enthält immer nur 3 zeichen.

memset(foo,program_parameter , strlen(&program_parameter));

// Wenn ich hier die var program_parameter ausgebe kommt das problem, ein segfault. Wieso?

printf("DEBBUG parameter: %c\n", foo)



Wäre froh für Hilfe.

Danke


newc0mer.

Boron
03-04-2006, 15:08
Nur argv[3] übergeben und nicht *argv[3].
argv[3] ist ein Zeiger auf einen String
*argv[3] ist nur das erste Zeichen des Strings

Willst du einen String an die Funktion function() übergeben?
Dann soltlest du auch das zweite Argument als char* schreiben und nicht nur als char.

newc0mer
04-04-2006, 11:31
hi, wenn ich nur argv[3] übergebe und function(int testvar, char * program_parameter) mache, dann bekomme ich beim compilern folgende warnung:

warning: passing are 2 of 'function' makes integer from pointer without a cast
warning: passing arg 2 of 'memset' makes interger from pointer without a cast

Und wenn ich es dann ausführem dann bekomme ich da auch gar nix mehr auf dem display, nicht mal der erste buchstaben oder so.

L00NIX
04-04-2006, 11:49
Zum segfault:



char foo[2]; // Variable enthält immer nur 3 zeichen.


Aha, wie viele Zeichen enthält dieses char-Array?

Richtig: zwei, nämlich foo[0] und foo[1]

Also muss es
char foo[3]; heißen mit den Elementen foo[0], foo[1] und foo[2]. Das Character foo[3] liegt dann bereits hinter dem array und löst bei Zugriff einen Segfault aus.

Gruß
L00NIX

Caveman
04-04-2006, 12:23
Die Funktion muss int function(int testvar, char** program_parameter); heißen. Da es sich doch um ein Array von char-Arrays handelt.
Aufgerufen wird sie dann mit var = function(testvar, argv);.

newc0mer
04-04-2006, 20:00
Zum segfault:
as Character foo[3] liegt dann bereits hinter dem array und löst bei Zugriein Array von char-Arraysff einen Segfault aus.

Aha... wird da dieses "Schulsszeichen" gesetzt? (das /0 ?).


ein Array von char-Arrays

Hmm wieso ein Array? Ich dachte (nach euren Posts) Das wäre ein Pointer auf ein Array?

Habe hier noch ein Problem:


memset(foo,program_parameter , strlen(&program_parameter));

Es heisst:

warning: passing arg 2 of 'memset' makes integer from pointer without a cast

man memset meint, memset füllt das konstante byte program_parameter in foo und gibt davon einen pointer zurück. jo, erm das ist jetzt halt ein pointer auf ein array, welches ich da reingebe und nicht des konstante byte :S... hat da grad noch jemand nen tipp?

Caveman
04-04-2006, 20:50
Wenn Du einen String in einen anderen kopieren willst, brauchst Du memcpy().
memset() setzt ein Zeichen in den Speicherbereich. (z.B. zum Initialisieren '\0')


void *memcpy( void *to, const void *from, size_t count );

jeebee
04-04-2006, 21:53
oder gerade die entsprechende <string.h> Funktion:

#include <string.h>
strcpy(char *dest, const char *src);

L00NIX
05-04-2006, 07:57
Aha... wird da dieses "Schulsszeichen" gesetzt? (das /0 ?).

Das Schlusszeichen \0 (NUL) terminiert in C Strings. Strings als solche gibt es in C ja nicht, es handelt sich um char-Arrays.

Wenn du z.B. einen Namen speichern willst, der maximal 20 Zeichen lang sein soll, brauchst du ein char-Array, das ein Zeichen (nämlich das NUL) mehr fasst:


char* name[21]; /* fasst 20 Zeichen und \0 */

Auch hier ist die Position name[21] bereits hinter dem Array.


Gruß
L00NIX

gorba
05-04-2006, 09:29
hehe hi gEry welcome back

nette sache, hab auch noch ne zwischenfrage, die nicht viel mit dem zu tun hatt aber schon was.

wen ich die adresse eines Array-elementes übergeben will (nicht die basisadresse) gibt es dan noch eine andere variante zu:
blubb = &array[5] ?

L00NIX
05-04-2006, 11:15
wen ich die adresse eines Array-elementes übergeben will (nicht die basisadresse) gibt es dan noch eine andere variante zu:
blubb = &array[5] ?

Ich kenne zumindest keine Schönere, komplizierter geht's immer. ;)

Boron
05-04-2006, 12:12
@gorba
typ array[10];
typ* blubb;

blubb = array; /* Zeiger auf erstes Element auf array vom Typ typ*/
blubb = &array[0]; /* Auch Zeiger auf erstes Element */
blubb = &array[3]; /* Zeiger auf viertes Element */Es gibt nichts Einfacheres.

newc0mer
05-04-2006, 20:34
Das Schlusszeichen \0 (NUL) terminiert in C Strings. Strings als solche gibt es in C ja nicht, es handelt sich um char-Arrays.

Wenn du z.B. einen Namen speichern willst, der maximal 20 Zeichen lang sein soll, brauchst du ein char-Array, das ein Zeichen (nämlich das NUL) mehr fasst:


char* name[21]; /* fasst 20 Zeichen und \0 */

Auch hier ist die Position name[21] bereits hinter dem Array.


Gruß
L00NIX

Hmm, ich dachte ein Array beginnt bei 0 - somit ein namen mit 20 zeichen ein array arr[20], dann 0-19 ist der name und 20 = \0 !?

thx to caveman and jeebbee too :)

jeebee
05-04-2006, 21:22
das array beginnt schon bei 0, aber wenn du es mit
char *name[20]; initialisierst, dann hast du ein Array mit 20 Feldern, was bedeutet, da ja das Array bei 0 anfängt, dass das letzte Feld mit
name[19] angesprochen wird.

L00NIX
05-04-2006, 21:24
Hmm, ich dachte ein Array beginnt bei 0 - somit ein namen mit 20 zeichen ein array arr[20], dann 0-19 ist der name und 20 = \0 !?

Ein Array beginnt auch bei 0, deswegen hat ein char a[20] eben 20 Elemente mit den Indizes 0-19. Das ist eben das typische Informatikerproblem, ob man nun von 0 oder von 1 anfängt zu zählen. ;)

Völlig unabhängig davon ist aber \0 ist auch ein Zeichen, dass gespeichert werden will und somit ein Feld reserviert werden muss.

In C++ werden die Strings mit Anfang und Länge gespeichert, so dass die Endmarkierung entfallen kann. C kennt ja genau genommen nicht mal Strings.

gorba
06-04-2006, 10:49
Ein Array beginnt auch bei 0, deswegen hat ein char a[20] eben 20 Elemente mit den Indizes 0-19. Das ist eben das typische Informatikerproblem, ob man nun von 0 oder von 1 anfängt zu zählen. ;)


rischtiig, da gibt es ja z.b. die "guten" funktionen die beim angegebenen Wert eins abzählen und die "bösen" die dir dan (wenn du nicht daran denkst) ein segfault um die ohren schmeissen.

Darum mach ich mir das leben (manchmal) leichter und setze makros ein, das fällt einem dann schnell auf:

#define MAX 10

char array[MAX]

irgendeinefunktion(array, MAX-1);

finde ich noch ganz hilfreich

L00NIX
06-04-2006, 16:06
Darum mach ich mir das leben (manchmal) leichter und setze makros ein, das fällt einem dann schnell auf:

#define MAX 10

char array[MAX]

irgendeinefunktion(array, MAX-1);

finde ich noch ganz hilfreich

Noch hilfreicher ist es, statt der fehleranfälligen Makros (#define) das ganze als Konstanten zu definieren:


const int MAX = 10;

int main()
{
char array[MAX];

[...]

return 0;
}


Im Gegensatz zu den Präprozessor-Direktiven erzeugen diese Konstanten dann auch Typfehler, etc.

gorba
07-04-2006, 08:23
ok.

wie meinst du fehleranfällig?
Da ein Makro ja eigentlich ein int ist (oder?) und ich ihn nur als int verwende, ist das ganze doch nicht fehleranfällig?

L00NIX
07-04-2006, 08:29
ok.

wie meinst du fehleranfällig?
Da ein Makro ja eigentlich ein int ist (oder?) und ich ihn nur als int verwende, ist das ganze doch nicht fehleranfällig?

Ein #define-Makro hat keinen Typ, es ist codierter Text (ascii, utf, etc.), der vom Präprozessor (!) ersetzt wird. Somit kann eine Typprüfung gar nicht stattfinden.

Auch witzig ist z.B.


#define private public
#define protected public


oder auch



#define main hier_gehts_los


Immer noch int? ;)

Gruß
L00NIX

gorba
07-04-2006, 10:41
=D oke oke...

ich weiss jetzt was du meinst, wenn man das ganze nun aber sinnvoll(!) einsetzt sehe ich keine gefahr.

und die dinger kann man so schön irgendwo im code hinsetzen..