Forum: Compiler & IDEs Array fixer Länge an Funktion übergeben


von ich (Gast)


Lesenswert?

Hallo,
um arrays an Funktionen zu übergeben, bietet sich ja ein Pointer an. 
Gibt es auch noch andere Möglichkeiten um ein Array mit einer fixen 
Größe an die Fkt. zu übergeben? Wie muss dann der funktionsprototyp 
aussehen?

von Konrad S. (maybee)


Lesenswert?

void f( int a[42] );

von Klaus W. (mfgkw)


Lesenswert?

(was aber faktisch aufs selbe rauskommt, eine Feldgrenzenüberprüfung 
o.ä. kann man da nicht erwarten...)

von Konrad S. (maybee)


Lesenswert?

So ist es.
Der sizeof-Operator lässt sich noch anwenden und die Größenangabe kann 
das Lesen des Codes erleichtern. Ich kann mich allerdings nicht daran 
erinnern, dass ich dieses Konstrukt in eigenem Code mal eingesetzt 
hätte. Pointer beißen nicht!

von Möp (Gast)


Lesenswert?

Naja, sizeof funkt zwar, aber ist eigentlich unnötig da ja die 
Arraygröße eh im Prototyp (und damit im aktuellen Objekt irgendwo) 
bekannt ist :-)

von Konrad S. (maybee)


Lesenswert?

Ja, genau, deswegen arbeite ich da nur mit Pointern.

von ich (Gast)


Lesenswert?

Gut, es handelt sich um 2 charakter Zeichen. Immer 2, nicht mehr und 
nicht weniger. Der Aufruf erfolgt mit Test("AB");, schade das sich das 
nicht belassen lässt.

von Oliver (Gast)


Lesenswert?

ich schrieb:
> Gut, es handelt sich um 2 charakter Zeichen. Immer 2, nicht mehr und
> nicht weniger.

Das das Array dabei die Länge 3 hat, ist dir aber bewusst, oder ?

Oliver

von Karl H. (kbuchegg)


Lesenswert?

Konrad S. schrieb:
> void f( int a[42] );

*Vorsicht!*
Das ist nichts anderes als eine glorifizierte andere Schreibweise für
1
void f( int* a);
nicht mehr und nicht weniger.
Da steckt NICHT mehr dahinter, auch wenn die Schreibweise da was anderes 
suggeriert.
1
#include <stdio.h>
2
3
void f( int a[42] )
4
{
5
  printf( "%d\n", sizeof( a ) );
6
}
7
8
int main()
9
{
10
  int b[9];
11
12
  f( b );
13
}

Die Ausgabe ist 4, weil auf meinem System ein Pointer 4 Bytes groß ist! 
Die Ausgabe hat nichts mit der tatsächlichen Größe von a innerhalb der 
Funktion oder gar mit der Arraygröße des Aufrufers zu tun!

Arrays werden in C an Funktionen übergeben, in dem die Startadresse des 
Arrays übergeben wird und die empfangende Funktion hat dafür eine 
passende Pointer Variable bereitzustellen. Punkt.


Meine persönlichen Meinung nach, sollte man um sowas
1
void f( int a[42] );
einen Bogen machen. Auf den ersten Blick mag das für Neulinge einfacher 
erscheinen. Ist es aber nicht. Denn hier werden unterschwellig Dinge 
suggeriert, die einfach nicht zutreffend sind. Die Arrayangabe oder gar 
die Angabe der Arraygröße haben an dieser Stelle absolut nichts zu 
sagen! Dei Arrayangabe kann an den Aufrufer noch ein gewisses Signal 
sein, wie der Parameter von der Funktion verwendet werden wird, was 
gegenüber Pointer ein gewisser dokumentarischer Vorteil sein kann. Aber 
wir wissen alle, wie das mit derartigen Konventionen ist .... man kann 
sich einfach nicht auf sie verlassen, solange sie nicht vom Compiler 
eingefordert und überprüft werden.

von ich (Gast)


Lesenswert?

Hallo, ich habe mit den Pointern doch ein Problem.

Prototyp ist z. B. der
1
void test( char *);


Funktionsaufruf

1
test("ABCD");

wird automatisch die Addresse der Speicherstelle von "A" übergeben oder?

wie muss jetzt die Funktion selbst aussehen?
1
void test(char foo[5])
2
{
3
    char lokales_arr[5];
4
5
    hier dann ursprüngliches array in neues array kopieren;
6
}
funktioniert, ich vermute aber das das Ganze nicht sauber ist, weil ich 
ja ein Array in den Funktionsparameter angebe, aber ein Pointer 
übergeben wird? Wie muss das Ganze stattdessen aussehen?

Ich möchte quasi die übergebenen Zeichen ABCD in ein anderes Array 
kopieren, welches noch andere Daten enthält.

von Dennis S. (eltio)


Lesenswert?

Da ein ordentlicher "String" in C eine Nullterminierung hat, könntest du 
das in einer While-Schleife Zeichen für Zeichen kopieren. strncpy sollte 
auch gehen, denke ich.

Gruß Dennis

von ich (Gast)


Lesenswert?

Da reinkopieren ist sicher kein Problem, da es immer eine bestimmte 
Länge ist und ich den Nullterminierung nicht brauche.

Ich habe ein Array "01234567890" und an Position 4 soll die 
Zeichenfolge, die an die Funktion übergeben wurde, kopiert werden. 
"0123ABCD890".

Allerdings geht es mir um den Funktionskopf,
1
void test(char foo[5])
 da ist meiner Meinung nch etwas faul, weil sie ja nicht mit dem 
Funktionsprototypen übereinstimmt.

von Malte S. (maltest)


Lesenswert?

Der lautet dann auch
1
void test(char* foo)
Warum willst du die vereinbarte Länge da unbedingt drin haben. Mehr als 
eine Vereinbarung ist sie eh nicht.

von ich (Gast)


Lesenswert?

Malte S. schrieb:
> Der lautet dann auchvoid test(char* foo)
> Warum willst du die vereinbarte Länge da unbedingt drin haben. Mehr als
> eine Vereinbarung ist sie eh nicht.

Muss nicht zwingend drinn sein, ist aber übersichtlicher.


Ok also void test(char* foo) und der Zugriff auf die einzelnen Elemente 
wie?

von Peter II (Gast)


Lesenswert?

ich schrieb:
> Ok also void test(char* foo) und der Zugriff auf die einzelnen Elemente
> wie?

foo[1] oder *(foo+1)

von Malte S. (maltest)


Lesenswert?

1
char test(char* foo) {
2
    return foo[1];
3
}

Aber nur, wenn du absolut garantieren kannst, dass test() immer ein 
ausreichend langes Array übergeben wird.

von Malte S. (maltest)


Lesenswert?

Willkommen in der wunderbaren Welt der Arrays und Pointer in C. Sie kann 
dir zu Füßen liegen oder unter selbigen zusammenbrechen. Das 
vollständige Verständnis jeder Indizierung und jeder Dereferenzierung, 
der Überblick über Herkunft und Zuverlässigkeit der Daten (Strings z.B.) 
und entsprechendes Einhalten der Grenzen des jeweiligen Speicherbereichs 
- ob in Gestellt eines Arrays oder eines blanken Pointers - helfen dir, 
dass am Ende nicht alles zusammenbricht ;)

von Arne Nonymous (Gast)


Lesenswert?

Malte S. schrieb:
> Aber nur, wenn du absolut garantieren kannst, dass test() immer ein
> ausreichend langes Array übergeben wird.

Seit C99 geht das teilweise:
1
char test(char foo[static 2]) {
2
    return foo[1];
3
}
So deklariert darf man keinen Nullpointer und kein Array mit einer Länge 
von weniger als zwei Elementen an die Funktion übergeben.

von Peter II (Gast)


Lesenswert?

Arne Nonymous schrieb:
> So deklariert darf man keinen Nullpointer und kein Array mit einer Länge
> von weniger als zwei Elementen an die Funktion übergeben.

und woher soll der compiler die länge wissen?

int i = rand(10);
int* a = (int*)malloc(sizeof(int)*i);
//oder c++ int[] a  = new int[i];

test(a) {
}

von Yalu X. (yalu) (Moderator)


Lesenswert?

Peter II schrieb:
> Arne Nonymous schrieb:
>> So deklariert darf man keinen Nullpointer und kein Array mit einer Länge
>> von weniger als zwei Elementen an die Funktion übergeben.
>
> und woher soll der compiler die länge wissen?

Der Compiler weiß das nicht und muss es auch nicht wissen. Das [static 
2] ist lediglich eine Zusicherung des Programmierers, dass das Array 
mindestens 2 Elemente enthält und kann vom Compiler zu 
Optimierungszwecken verwendet werden. Für die Einhaltung dieser 
Zusicherung ist der Programmierer aber selber verantwortlich. Der 
Compiler überprüft sie nicht notwendigerweise.

von Konrad S. (maybee)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Die Ausgabe ist 4, weil auf meinem System ein Pointer 4 Bytes groß ist!

Uppps, Asche auf mein Haupt!

von Manni (Gast)


Lesenswert?

Suchst Du so was?
1
#include <stdio.h>
2
#include <string.h>
3
4
typedef struct
5
{
6
  char ch[3];
7
} String3_s;
8
9
void func( String3_s string3 )
10
{
11
  printf( "%s\n", &string3.ch[0] );
12
  printf( "%lu\n", sizeof( string3 ) );
13
}
14
15
int main( void )
16
{
17
    // C89
18
    //String3_s string3;
19
    //strcpy( &string3.ch[0], "AB" );
20
  
21
    // C99
22
    String3_s string3 = { .ch = "AB" };
23
  func( string3 );
24
}
25
  
26
  
27
}

Ausgabe:
fjhf@hjhgjk:~/test$ ./a.out
AB
3

Gruss,
Manni

von Manni (Gast)


Lesenswert?

Sorry, da ist eine Klammer zu viel, keine Ahnung wo die herkommt.
Muss mal die Anleitung zum Forum lesen.

Gruß,
Manni

von Dr. Sommer (Gast)


Lesenswert?

Elegant & sicher geht so:
1
#include <iostream>
2
#include <array>
3
4
void fun (std::array<int,7> arr) {
5
  for(auto x : arr) {
6
    std::cout << x;
7
  }
8
}
9
10
void fun2 (const std::array<int,7>& arr) {
11
  for(auto x : arr) {
12
    std::cout << x;
13
  }
14
}
15
16
int main () {
17
  fun ({{1, 2, 3, 4, 5, 6, 7}});
18
  fun2 ({{1, 2, 3, 4, 5, 6, 7}});
19
}
So ist auch sichergestellt dass man nicht zu viel übergibt, und dass, 
falls man zu wenig übergibt, die anderen Elemente default-initialisiert 
werden (Integer auf 0, Klassen per Default-Konstruktor) - somit keine 
Speicherfehler möglich. Die 1. Variante kopiert dabei den kompletten 
Inhalt in den Funktions-scope, die 2. übergibt nur eine Referenz 
(normalerweise schneller).

von Dr. Sommer (Gast)


Lesenswert?

PS: So funktioniert sogar sizeof(arr) und arr.size() "sinnvoll".

von Martin (Gast)


Lesenswert?

Also bei mir würde die Funktion auch so aussehen:
1
char* teilstring(const char* string, unsigned int groesse)
2
{
3
  char *teilstring = (char*)malloc(sizeof(char)*(groesse+1));
4
  teilstring[groesse]='\0';
5
6
  for(unsigned int counter=0;counter<groesse; counter++) teilstring[counter]=string[counter];
7
8
  return teilstring;
9
}

Man übergibt einen String als Pointer und eine Variable für die Größe 
des Rückgabestrings.
Übergibt man also ein String/Array mit Inhalt "Hallo Welt!" und Größe=4 
dann wird "Hall" zurückgegeben... Da ist aber noch nicht die mögliche 
Überlänge von int groesse in Bezug auf die tatsächliche Länge des Arrays 
berücksichtigt!

von Martin (Gast)


Lesenswert?

Hier mit Überlängenkorrektur:
1
char* teilstring(char* string, unsigned int groesse)
2
{
3
  char *teilstring = (char*)malloc(sizeof(char)*(groesse+1));
4
  teilstring[groesse]='\0';
5
6
  for(unsigned int counter=0;counter<groesse; counter++)
7
  {
8
    teilstring[counter]=string[counter];
9
    if (string[counter]=='\0') break;
10
  }
11
12
  return teilstring;
13
}

von Dr. Sommer (Gast)


Lesenswert?

Martin schrieb:
> Also bei mir würde die Funktion auch so aussehen:
Das ist genau das gleiche was strndup macht?! Btw, sizeof(char) ist 
immer 1, das kann man also weglassen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Manni schrieb:
> //strcpy( &string3.ch[0], "AB" );

Das geht auch lesbarer:
1
strcpy(string3.ch, "AB");

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.