Warum wird eine Funktion mit einem Array-Parameter bestimmter Größe durch einen Zeiger ersetzt?

Lesezeit: 5 Minuten

Warum wird eine Funktion mit einem Array Parameter bestimmter Grose durch
CsTamas

Bei folgendem Programm

#include <iostream>

using namespace std;

void foo( char a[100] )
{
    cout << "foo() " << sizeof( a ) << endl;
}

int main()
{
    char bar[100] = { 0 };
    cout << "main() " << sizeof( bar ) << endl;
    foo( bar );
    return 0;
}

Ausgänge

main() 100
foo() 4
  1. Warum wird das Array als Zeiger auf das erste Element übergeben?
  2. Ist es ein Erbe von C?
  3. Was sagt die Norm?
  4. Warum wird die strikte Typsicherheit von C++ fallen gelassen?

  • Ich verwende in diesen Fällen immer std::array, vermeidet, dass ich mich mit solchen Problemen befassen muss, und funktioniert auch mit std-Algorithmen

    – paulm

    8. September 2014 um 9:39 Uhr

  • Welche strenge Art von Sicherheit? Wer hat strenge Typensicherheit versprochen? In C++ gibt es so etwas nicht.

    – n. 1.8e9-wo-ist-meine-Aktie m.

    8. September 2014 um 9:58 Uhr

  • TL; DR für die folgenden Antworten: Arrays werden zu Zeigern, wenn sie an die Funktion übergeben werden. Wenn Sie also ihre Größe überprüfen, erhalten Sie nur die Größe eines Zeigers. Wenn Sie nur mit C arbeiten, kann ich nur vorschlagen, dass Sie die Größe, die Sie aus dem Array herausholen möchten, als weiteren Parameter vorberechnen.

    – Superkat

    27. Dezember 2015 um 22:04 Uhr


  • Relevanter Linus-Rant

    – Millie Smith

    4. Dezember 2017 um 21:51 Uhr

  • Verwandt: Bestimmen Sie die Größe des Arrays, wenn es an die Funktion übergeben wird

    – Gabriel Staples

    24. September 2020 um 21:17 Uhr

Warum wird eine Funktion mit einem Array Parameter bestimmter Grose durch
Richard Korden

Ja, es ist von C geerbt. Die Funktion:

void foo ( char a[100] );

Der Parameter wird so angepasst, dass er ein Zeiger ist, und wird so zu:

void foo ( char * a );

Wenn Sie möchten, dass der Array-Typ erhalten bleibt, sollten Sie eine Referenz auf das Array übergeben:

void foo ( char (&a)[100] );

C++ ’03 8.3.5/3:

…Der Typ einer Funktion wird anhand der folgenden Regeln bestimmt. Der Typ jedes Parameters wird von seinem eigenen decl-specifier-seq und declarator bestimmt. Nachdem der Typ jedes Parameters bestimmt wurde, wird jeder Parameter vom Typ „Array von T“ oder „Funktion, die T zurückgibt“ so angepasst, dass er „Zeiger auf T“ oder „Zeiger auf Funktion, die T zurückgibt“ ist.

Zur Erklärung der Syntax:

Suchen Sie in Google nach der “Rechts-Links”-Regel; Eine Beschreibung habe ich gefunden Hier.

Es würde auf dieses Beispiel ungefähr wie folgt angewendet werden:

void foo (char (&a)[100]);

Beginnen Sie bei der Kennung ‘a’

‘a’ ist ein

Gehe nach rechts – wir finden a ) Also kehren wir die Richtung um und suchen nach dem (. Als wir uns nach links bewegen, passieren wir &

‘a’ ist eine Referenz

Nach dem & Wir erreichen die Öffnung ( also kehren wir wieder um und schauen nach rechts. Wir sehen jetzt [100]

‘a’ ist ein Verweis auf ein Array von 100

Und wir kehren die Richtung wieder um, bis wir erreichen char:

‘a’ ist ein Verweis auf ein Array von 100 Zeichen

  • Letzteres hat den Nachteil, dass die Arraygröße in der Funktionssignatur fest verdrahtet ist. Eine Funktionsvorlage kann das vermeiden.

    – sbi

    25. August 2009 um 13:29 Uhr

  • Es ist wahrscheinlich erwähnenswert, dass die Verwendung eines std::vector alle Probleme im Zusammenhang mit der Übergabe von Arrays ordentlich umgeht.

    – markh44

    25. August 2009 um 14:02 Uhr

  • Dies läuft darauf hinaus, dass einfache Array-Parameter in C/C++ eine Fiktion sind – sie sind wirklich Zeiger. Array-Parameter sollten so weit wie möglich vermieden werden – sie verwirren wirklich nur die Dinge.

    – Michael Burr

    25. August 2009 um 17:04 Uhr

  • Nur ein Nit-Pick: Der Funktionsparameter zerfällt nicht zum Zeiger. es ist angepasst zum Zeiger. Ein Array-Name, der als Funktion verwendet wird Streit kann Verfall zu einem Zeiger, wenn der Funktionsparameter ein Zeiger ist.

    – Juanchopanza

    6. April 2015 um 14:50 Uhr

  • Bravo für die Erklärung der Regel, da der Link jetzt ein 404 ist.

    – Gsamaras

    8. April 2015 um 13:43 Uhr


1647258610 49 Warum wird eine Funktion mit einem Array Parameter bestimmter Grose durch
sbi

Jawohl. In C und C++ können Sie keine Arrays an Funktionen übergeben. So ist es nun einmal.

Warum machst du überhaupt einfache Arrays? Hast Du Dir angesehen boost/std::tr1::array/std::array oder std::vector?

Beachten Sie, dass Sie jedoch eine Referenz auf ein Array beliebiger Länge an eine Funktion übergeben können Vorlage. Aus dem Kopf:

template< std::size_t N >
void f(char (&arr)[N])
{
  std::cout << sizeof(arr) << '\n';
}

  • Aber Sie können “Verweis auf Array” übergeben.

    – Richard Corden

    25. August 2009 um 13:24 Uhr

  • @ Richard: Ich habe das gerade hinzugefügt, während Sie Ihren Kommentar geschrieben haben. :)

    – sbi

    25. August 2009 um 13:28 Uhr

  • Das Übergeben von Verweisen auf Arrays ist nicht auf “Funktionsvorlagen” beschränkt. Sie können ein Array als Referenz an Nicht-Vorlagenfunktionen übergeben. Der Vorteil der Verwendung einer Funktionsvorlage besteht darin, dass Sie den Array-Index ableiten können, wodurch Sie die Funktion für Array-Typen unterschiedlicher Größe aufrufen können.

    – Richard Corden

    25. August 2009 um 13:29 Uhr

  • @CsTamas, ja, die Regeln für die Übergabe von Arrays und Objekten sind in C unterschiedlich. Strukturen werden tatsächlich nach Wert kopiert, wenn sie als Parameter übergeben werden. Arrays werden als Zeiger auf ihr erstes Element behandelt. (Arrays und Zeiger in C sind sehr miteinander verbunden. Sie sind nicht dasselbe, aber zum Zweck der Parameterübergabe sind sie identisch.)

    – Tyler McHenry

    25. August 2009 um 13:34 Uhr

  • Es gibt jetzt std::array.

    – Trevor Hickey

    21. April 2016 um 5:47 Uhr

Es gibt ein großartiges Wort in der C/C++-Terminologie, das für statische Arrays und Funktionszeiger verwendet wird – Verfall. Betrachten Sie den folgenden Code:

int intArray[] = {1, 3, 5, 7, 11}; // static array of 5 ints
//...
void f(int a[]) {
  // ...
}
// ...
f(intArray); // only pointer to the first array element is passed
int length = sizeof intArray/sizeof(int); // calculate intArray elements quantity (equals 5)
int ptrToIntSize = sizeof(*intArray); // calculate int * size on your system

  • Und? Dies weist bestenfalls indirekt darauf hin was das passiert. Der OP hat nachgefragt warum Die Sprache ist so eingerichtet. Außerdem ist “statisches Array” ein verwirrender Begriff, wenn das, was Sie wirklich meinen, dynamisch zugewiesen wird. Technisch gesehen hat das Array, das Sie gezeigt haben extern Verknüpfung, nicht static. Und ich bin mir nicht sicher, was Funktionszeiger hier mit irgendetwas zu tun haben?

    – Unterstrich_d

    30. August 2016 um 15:21 Uhr


1001390cookie-checkWarum wird eine Funktion mit einem Array-Parameter bestimmter Größe durch einen Zeiger ersetzt?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy