was ist `int *userMask[3][4]` zeigt auf?

Lesezeit: 6 Minuten

Benutzer-Avatar
Tim

Ich ändere Code und bin auf eine Erklärung gestoßen, die ich nicht verstehe:

int *userMask[3][4] = {0};

Worauf deutet das genau hin? Ist es eine Matrix, in der jedes Element ein Zeiger ist? Oder zeigt es auf eine Größenmatrix [3][4]?

Vielen Dank


Ich denke, meine Frage ist, wie userMask[2][maskElement][user] kann funktionieren, wenn es als deklariert ist int. Müsste userMask nicht sein int[] damit das richtig funktioniert? Ich muss das nicht richtig verstehen…

Nebenbei bemerkt, vielen Dank für Ihren Vorschlag zu cdecl Robert. Weiß jedoch jemand, wie man es in einer XP-Eingabeaufforderung verwendet? Ich kann nur einen Syntaxfehler bekommen 🙁

Benutzer-Avatar
Johannes Schaub – litb

Kurze Antwort

Die gegebene userMask wird als deklariert

int *userMask[3][4];

dann userMask Typ hat int*[3][4]. Es ist ein 2D-Array von Zeigern auf int. Die Größe der äußeren Dimension ist 3, die Größe der inneren Dimension ist 4. Wirklich, das ist nichts anderes als ein 1d-Array mit 3 Elementen, dessen Elementtyp ein weiterer 1d-Array mit 4 Elementen ist, welcher Elementtyp ist int*.

Schritte erklärt

Also, wenn du es tust

userMask[2][maskElement][user]

dann wählen Sie im Wesentlichen mit den ersten beiden Indizes den jeweiligen Zeiger aus dem 2d-Array aus:

int * p = userMask[2][maskElement];

dann wählen Sie ein int irgendwo versetzt von diesem Zeiger aus, indem Sie es tun

p[user]

jetzt ist dieser Code alles drin userMask[2][maskElement][user].

Gültiger C-Code

Um es Schritt für Schritt mit gültigem C-Code zu tun (keine Sorge, wenn Sie im Folgenden noch nicht alles verstehen):

int * userMask[3][4] = { { 0 } };
int ** pa = userMask[2]; /* int*[4] becomes int** implicitly */
int * pi = pa[maskElement];
int i = pi[user];

assert(i == userMask[2][maskElement][user]);

Unterschied zwischen Arrays und Zeigern

Ich glaube, ich zeige dir etwas Wichtiges. Das obige Array tut es nicht enthalten Zeiger auf Arrays. Schauen wir uns an, wie unterschiedlich sie sich verhalten, was viele C-Programmierer nicht erwarten:

int array[5][4][3];
/* int[4][3] implicitly converts to int(*)[3] (pointer to first element) */
int (*parray)[3] = array[0]; 
int ** pint = (int**) array[0]; /* wrong!! */

Nun, was wird passieren, wenn wir das tun parray[1] und pint[1] ? Der erste wird parray by vorrücken sizeof(int[3]) Bytes (3 * sizeof(int)), die zweite rückt nur um vor sizeof( int* ) Byte. Also tatsächlich, während der erste Ihnen das richtige Array gibt array[0][1]die zweite wird dir geben ( char * )array[0] + sizeof( int* ), das ist irgendwo, wo wir es nicht wirklich wollen. Aber es geht nicht nur darum, den falschen Offset zu erwischen. Da es nicht weiß, dass auf ein Array zugegriffen wird, versucht es zu interpretieren, worum es geht pint[1] als ein int*. Angenommen, Ihr Array wurde mit initialisiert 0x00. Dann wird es den nächsten Indexschritt basierend auf der Adresse 0x00 (Doing pint[1][0] zum Beispiel). Oh nein – völlig undefiniertes Verhalten! Es ist also wirklich wichtig, den Unterschied zu betonen.

Fazit

Das war mehr, als Sie verlangt haben, aber ich denke, es ist ziemlich wichtig, diese Details zu kennen. Besonders wenn Sie 2D-Arrays an Funktionen übergeben möchten, ist dieses Wissen sehr nützlich.

  • Wenn das der Fall ist, bin ich immer noch etwas verwirrt. Das userMask-Array wird später verwendet als: if(userMask[2][maskElement][user] && blah) result = true; Wie kann dieser Zeiger auf ein int referenziert werden? [user] so was? Es ist kein int-Array, es ist ein int, richtig?

    – Tim

    8. November 2008 um 16:17 Uhr

  • Das OP fragte nach C, nicht nach C++.

    – Robert Gamble

    8. November 2008 um 17:55 Uhr

  • Ups, nicht bemerkt. Tut mir leid, ich werde beim nächsten Mal genauer lesen 🙂

    – Johannes Schaub – litb

    8. November 2008 um 17:58 Uhr

Benutzer-Avatar
ChrisN

Dies ist ein zweidimensionales Array, bei dem jedes Element ein Zeiger auf ein ist intund alle Zeiger werden auf Null initialisiert.

In Ihrem Follow-up zeigen Sie, dass das Array wie folgt verwendet wird:

if(userMask[2][maskElement][user] && blah)
    result = true;

In diesem Fall ist jedes Element in userMask sollte eigentlich auf ein Array von zeigen ints. (Ein int* kann auf einen einzigen hinweisen int oder eine Reihe von ints). Um dies festzustellen, überprüfen Sie den Code, der Werte zuweist userMask. Es ist zum Beispiel möglich zu schreiben:

int userArray[2] = { 10, 20 };

userMask[0][0] = userArray; // userMask[0][0] points to the
                            // first element of userArray.

Dann indiziert der folgende Code in userArray:

int value = userMask[0][0][1]; // sets value = userArray[1], giving 20.

Benutzer-Avatar
Robert Glück

int *userMask[3][4] = {0};

ist ein zweidimensionales Array, bei dem jedes Mitglied ein Zeiger auf int ist. Außerdem werden alle Member mit Nullzeigern initialisiert.

int (*userMask)[3][4];

wäre ein Zeiger auf ein zweidimensionales Array von Ints. Klammern in C binden enger als *, daher werden die Klammern benötigt, um einen Zeiger auf ein Array zu erstellen.

cdecl ist ein einfaches Dienstprogramm, das Sie herunterladen können, um komplexe Deklarationen zu erklären:

cdecl> explain int *userMask[3][4]
declare userMask as array 3 of array 4 of pointer to int

Es kann auch das Gegenteil bewirken:

cdecl> declare userMask as pointer to array 3 of array 4 of int
int (*userMask)[3][4]

  • Alle Member sind ohne Initialisierung null. Alle Mitglieder werden auf 0 initialisiert. Es gibt einen Unterschied, auch wenn es ein feiner ist.

    – Schluckauf

    8. November 2008 um 16:54 Uhr

  • @tloach, es tut mir leid, aber nichts von dem, was du gesagt hast, ergibt für mich einen Sinn. C initialisiert Variablen nicht automatisch, es sei denn, sie sind statisch, und ich weiß nicht, was Ihrer Meinung nach der Unterschied zwischen der Initialisierung von Zeigern auf 0 oder null ist, aber es gibt keine.

    – Robert Gamble

    8. November 2008 um 16:59 Uhr

if(userMask[2][maskElement][user] && blah)
   result = true;

Der zweite Teil hier ist, dass es in C keine Arrays gibt; es gibt nur Zeigerarithmetik. Per Definition, p[i] ist immer gleichbedeutend mit *(p+i) Also

userMask[2][maskElement][user]

ist äquivalent zu

*((userMask[2][maskElement])+user)

Der Code weist irgendwo einen Vektor (ich würde wetten, dass er von einem malloc(3c) oder einem ähnlichen Aufruf stammt) dem Zeiger in diesem Array zu; jetzt sagt dein if

WENN das user-te Element des Vektors bei userMask[2][maskElement] ist ungleich Null

DANN WENN blah ist nicht null (Aufgrund der Kurzschlussauswertung von && wird die zweite Konjunktion nicht ausgewertet, wenn die erste Konjunktion 0 ist)

DANN Set Ergebnis = wahr.

Benutzer-Avatar
Charly Martin

Wende die Inside-Out-Regel an.

int *userMask[3][4] = {0};

Beginnend mit dem Innerpost-Teil der Erklärung,

userMask

ist der Name

userMask[3] 

weist Platz für (ist ein Vektor von) 3 von ihnen zu

userMask[3][4] 

weist Platz für 4 zu userMask[3]‘s

int *

sagt uns das userMask Elemente sind Typzeiger auf int

und dann = {0} ist ein Initialisierer, in dem sich alle Elemente befinden 0. So

int *userMask[3][4] = {0};

ist ein 3×4-Array von int *, initialisiert auf 0.

Benutzer-Avatar
Cameron

Ich denke, diese Anweisung greift auf die dritte Zeile des usermask-Arrays zu und greift dann auf den maskElement-ten Zeiger in dieser Zeile zu, und da dies ein int-Zeiger ist, kann sie auf den Anfang eines int-Arrays zeigen (denken Sie an Zeichenfolgen), was ich Nehmen Sie an, dass dies der Fall ist und dass das Array vom Benutzer unterindiziert ist.

Benutzer-Avatar
pdc

userMask[2] ist vom Typ int*[],
userMask[2][maskElement] ist vom Typ int*,
und so userMask[2][maskElement][user] ist vom Typ int.

Die Erklärung

int *userMask[3][4] = {0};

ist eine Abkürzung für

int *userMask[3][4] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}};

wobei jede der Nullen implizit umgewandelt wird (int*)0.

1361840cookie-checkwas ist `int *userMask[3][4]` zeigt auf?

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

Privacy policy