Initialisieren des gesamten 2D-Arrays mit einem Wert

Lesezeit: 7 Minuten

Benutzeravatar von Kraken
Krake

Mit folgender Erklärung

int array[ROW][COLUMN]={0};

Ich bekomme das Array mit allen Nullen, aber mit der folgenden

int array[ROW][COLUMN]={1};

Ich bekomme das Array nicht mit allen einem Wert. Der Standardwert ist immer noch 0.

Warum dieses Verhalten und wie kann ich mit allen 1 initialisieren?

EDIT: Ich habe gerade verstanden, dass mit memset mit dem Wert 1, wird jedes Byte auf 1 gesetzt und daher wird der tatsächliche Wert jeder Array-Zelle nicht 1 sein, aber 16843009. Wie setze ich es auf 1?

  • @ckruse: Die Frage ist nicht Wiees ist Warum.

    – masud

    20. März 2013 um 10:29 Uhr


  • @MM. Antwort gibt es in dem von mir verlinkten Thread.

    – ckruse

    20. März 2013 um 10:30 Uhr

  • Das Problem war tatsächlich why and how beide. 🙂

    – Kraken

    20. März 2013 um 10:32 Uhr

  • @Kraken Die Frage in Ihrer Bearbeitung sollte vielleicht als separate Frage von dieser gepostet werden.

    – Ludin

    20. März 2013 um 10:51 Uhr

  • @Kraken Eigentlich habe ich diese Frage hier gefunden. Ich würde empfehlen, wie in meiner Antwort vorgeschlagen (natürlich!) Zu tun und sich nicht auf GCC-Erweiterungen zu verlassen.

    – Ludin

    20. März 2013 um 10:53 Uhr


Benutzeravatar von Lundin
Lundin

Sie bekommen dieses Verhalten, weil int array [ROW][COLUMN] = {1}; tut nicht bedeutet “alle Elemente auf eins setzen”. Lassen Sie mich versuchen, Schritt für Schritt zu erklären, wie das funktioniert.

Die explizite, übermäßig klare Art, Ihr Array zu initialisieren, wäre wie folgt:

#define ROW 2
#define COLUMN 2

int array [ROW][COLUMN] =
{
  {0, 0},
  {0, 0}
};

In C können Sie jedoch einige Elemente in einem Array (oder Struct/Union) weglassen. Du könntest zum Beispiel schreiben:

int array [ROW][COLUMN] =
{
  {1, 2}
};

Das heißt, initialisieren Sie die ersten Elemente auf 1 und 2 und die restlichen Elemente “als ob sie eine statische Speicherdauer hätten”. In C gibt es eine Regel, die besagt, dass alle Objekte mit statischer Speicherdauer, die nicht explizit vom Programmierer initialisiert werden, auf Null gesetzt werden müssen.

Im obigen Beispiel wird also die erste Zeile auf 1,2 und die nächste auf 0,0 gesetzt, da wir ihnen keine expliziten Werte gegeben haben.

Als nächstes gibt es eine Regel in C, die einen lockeren Klammerstil erlaubt. Das erste Beispiel könnte genauso gut geschrieben werden als

int array [ROW][COLUMN] = {0, 0, 0, 0};

Obwohl dies natürlich ein schlechter Stil ist, ist es schwerer zu lesen und zu verstehen. Aber diese Regel ist bequem, weil sie uns erlaubt zu schreiben

int array [ROW][COLUMN] = {0};

was bedeutet: “Die allererste Spalte in der ersten Zeile auf 0 initialisieren und alle anderen Elemente so, als ob sie eine statische Speicherdauer hätten, dh sie auf Null setzen.”

daher, wenn Sie es versuchen

int array [ROW][COLUMN] = {1};

es bedeutet “die allererste Spalte in der ersten Zeile auf 1 initialisieren und alle anderen Elemente auf Null setzen”.

  • Danke dafür, kann ich irgendetwas tun, um das gesamte Array mit 1 zu initialisieren? wenn man bedenkt, dass meine Zeilen und Spalten Hunderte groß sind?

    – Kraken

    20. März 2013 um 10:51 Uhr

  • @Kraken Mit Makrotricks. Sieh dir das an.

    – Ludin

    24. Oktober 2014 um 6:22 Uhr

  • Bin ich es nur oder brauchst du den zweiten Satz Klammern: int array [ROW][COLUMN] = {{0}};

    – Benutzer1794469

    17. Mai 2016 um 15:38 Uhr

  • @ user1794469 Nein, tust du nicht.

    – Ludin

    17. Mai 2016 um 19:31 Uhr

  • @ user1794469 Ja, und das ist gut, denn in den meisten Fällen ist das Überspringen von geschweiften Klammern eine schlechte Übung. Aber der Compiler nicht haben eine Diagnose zu stellen. Bezüglich guter/schlechter Praxis für diesen Fall siehe meine Antwort auf diese Frage.

    – Ludin

    18. Mai 2016 um 6:13 Uhr

Benutzeravatar von user2021512
Benutzer2021512

Wenn Sie das Array initialisieren möchten -1 dann kannst du folgendes verwenden

memset(array, -1, sizeof(array[0][0]) * row * count)

Aber das wird funktionieren 0 und -1 nur

  • Es ist einfacher, “sizeof(array)” anstelle von “sizeof(array) zu verwenden[0][0]) * Reihenanzahl”.

    – Vladyslaw Savchenko

    20. Februar 2016 um 12:49 Uhr


  • Es funktioniert für jedes konstante Byte, obwohl mir nicht klar ist, was außerdem nützlich wäre 0000 und 1111

    – Benutzer1794469

    17. Mai 2016 um 15:36 Uhr


  • beinhalten müssen <cstring> in c++

    – mtk

    16. Juli 2016 um 6:55 Uhr

  • Dies funktioniert auch für jeden Wert, der aus demselben Byte besteht, das immer wieder wiederholt wird, aber nicht anders.

    – Plas

    3. April 2021 um 4:01 Uhr

  • Sie können auch 0x7f oder 0x3f einstellen, um eine wirklich große Zahl zu erhalten und als unendlich zu verwenden.

    – Michael Yang

    3. Mai 2021 um 13:03 Uhr

Benutzeravatar von teppic
teppisch

int array[ROW][COLUMN]={1};

Dies initialisiert nur die Erste Element auf 1. Alles andere bekommt eine 0.

Im ersten Fall machen Sie dasselbe – Sie initialisieren das erste Element auf 0, und der Rest wird standardmäßig auf 0 gesetzt.

Der Grund ist einfach: Bei einem Array initialisiert der Compiler jeden Wert, den Sie nicht mit 0 angeben.

Mit einer char Array, das Sie verwenden könnten memset um jedes Byte zu setzen, aber das funktioniert im Allgemeinen nicht mit an int array (obwohl es für 0 in Ordnung ist).

Ein General for Schleife wird dies schnell tun:

for (int i = 0; i < ROW; i++)
  for (int j = 0; j < COLUMN; j++)
    array[i][j] = 1;

Oder möglicherweise schneller (je nach Compiler)

for (int i = 0; i < ROW*COLUMN; i++)
  *((int*)a + i) = 1;

  • @Kraken – Das tut es nicht – 0 initialisiert auch nur den ersten Wert. Es initialisiert dann den ganzen Rest mit 0 standardmäßig.

    – teppisch

    20. März 2013 um 10:27 Uhr


  • @EricPostpischil also, es setzt alle Bytes mit 1, also wenn ich eine 32-Bit-Ganzzahl betrachte, dann wenn meine value Feld ein memset 1 ist, dann ist der tatsächliche Wert in der Matrix aber nicht 1 2^0 + 2^8 + 2^16 + 2^24?

    – Kraken

    20. März 2013 um 10:38 Uhr

  • @Kraken: Im Wesentlichen ja. memset setzt jedes Byte in seinem Ziel auf den ihm zugewiesenen Wert, was nicht funktioniert, um an zu setzen int bis 1. memset kann nicht verwendet werden, um Werte von Objekten mit mehreren Bytes festzulegen, es sei denn, Sie möchten, dass jedes Byte des Objekts auf denselben Wert festgelegt wird.

    – Eric Postpischil

    20. März 2013 um 10:41 Uhr

  • @EricPostpischil Also gibt es keine andere Möglichkeit, als jedes manuell zu initialisieren? Wenn man bedenkt, dass meine Zeilen und Spalten sogar in den paar Tausend sind?

    – Kraken

    20. März 2013 um 10:44 Uhr

  • @Kraken Ich habe eine Erklärung gepostet, warum {1} nicht funktioniert. Und tatsächlich gibt es keinen anderen Weg als die manuelle Initialisierung. Sie müssen zwar nicht Tausende von Zahlen eingeben, es gibt Makrotricks, aber das ist vielleicht ein Thema für eine andere Frage.

    – Ludin

    20. März 2013 um 10:50 Uhr

Verwenden Sie die folgende Methode, um das 2D-Array mit Null zu initialisieren:
int arr[n][m] = {};

HINWEIS : Die obige Methode funktioniert nur zum Initialisieren mit 0;

Beachten Sie, dass GCC eine Erweiterung für die hat ausgewiesener Initialisierer Notation, die für den Kontext sehr nützlich ist. Es ist auch erlaubt clang ohne Kommentar (teilweise, weil es versucht, mit GCC kompatibel zu sein).

Die Erweiterungsnotation ermöglicht Ihnen die Verwendung ... um einen Bereich von Elementen festzulegen, die mit dem folgenden Wert initialisiert werden sollen. Zum Beispiel:

#include <stdio.h>

enum { ROW = 5, COLUMN = 10 };

int array[ROW][COLUMN] = { [0 ... ROW-1] = { [0 ... COLUMN-1] = 1 } };

int main(void)
{
    for (int i = 0; i < ROW; i++)
    {
        for (int j = 0; j < COLUMN; j++)
            printf("%2d", array[i][j]);
        putchar('\n');
    }
    return 0;
}

Die Ausgabe ist wenig überraschend:

 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1

Beachten Sie, dass Fortran 66 (Fortran IV) Wiederholungszähler für Initialisierer für Arrays hatte; Es kam mir immer seltsam vor, dass C sie nicht bekam, als der Sprache bestimmte Initialisierer hinzugefügt wurden. Und Pascal verwendet die 0..9 Notation, um den Bereich von 0 bis einschließlich 9 zu bezeichnen, aber C verwendet sie nicht .. als Token, daher ist es nicht verwunderlich, dass es nicht verwendet wurde.

Beachten Sie, dass die Leerzeichen um die ... Notation sind grundsätzlich obligatorisch; Wenn sie an Zahlen angehängt sind, wird die Zahl als Fließkommazahl interpretiert. Zum Beispiel, 0...9 würde als tokenisiert werden 0., ., .9, und Fließkommazahlen sind als Array-Indizes nicht zulässig. Mit den genannten Konstanten ...ROW-1 würde keine Probleme verursachen, aber es ist besser, sich an die sicheren Gewohnheiten zu gewöhnen.


Ergänzungen:

Ich stelle nebenbei fest, dass GCC 7.3.0 ablehnt:

int array[ROW][COLUMN] = { [0 ... ROW-1] = { [0 ... COLUMN-1] = { 1 } } };

wo es einen zusätzlichen Satz geschweifter Klammern um den skalaren Initialisierer gibt 1 (error: braces around scalar initializer [-Werror]). Ich bin mir nicht sicher, ob das richtig ist, da Sie normalerweise Klammern um einen Skalar angeben können int a = { 1 };, was der Standard ausdrücklich erlaubt. Ich bin mir auch nicht sicher, ob es falsch ist.

Ich frage mich auch, ob eine bessere Notation wäre [0]...[9] — die eindeutig ist, mit keiner anderen gültigen Syntax verwechselt werden kann und Verwechslungen mit Fließkommazahlen vermeidet.

int array[ROW][COLUMN] = { [0]...[4] = { [0]...[9] = 1 } };

Vielleicht würde der Normenausschuss das in Betracht ziehen?

Benutzeravatar von Jogendra Kumar
Jogendra Kumar

Verwenden Vektor Array stattdessen:

vector<vector<int>> array(ROW, vector<int>(COLUMN, 1));

Benutzeravatar des Inhalators
Inhalator

char grid[row][col];
memset(grid, ' ', sizeof(grid));

Das dient zum Initialisieren von char-Array-Elementen für Leerzeichen.

1420960cookie-checkInitialisieren des gesamten 2D-Arrays mit einem Wert

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

Privacy policy