Array fixer Länge an Funktion übergeben

#3255590
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.
Gast #3255927
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.
Gast #3255976
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.
Gast #3256004
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?
#3256029
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 ;)
Gast #3256286
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.
Gast #3256291
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) {
}
Moderator #3256364
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.
Gast #3256754
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
Gast #3256820
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).
Gast #3256852
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!
Gast #3256854
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
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren