Welcher Datentyp für Indizes?



  • Hallo ihr,

    auch wenn es ein bisschen eine philosophische Frage ist, so ist es doch etwas, worüber ich mir Gedanken mache, daher würde ich gerne einmal eure Meinungen dazu hören... Es geht eigentlich um etwas total Banales:

    double vec[42];
    
    // Variante 1
    for (int i = 0; i < 42; i++)
        vec[i] *= 3.14;
    
    // Variante 2
    for (unsigned int i = 0; i < 42; i++)
        vec[i] *= 3.14;
    
    // Variante 3
    for (std::size_t i = 0; i < 42; i++)
        vec[i] *= 3.14;
    

    Welche Variante benutzt ihr? Macht ihr es davon abhängig, ob vec ein Array aus Bytes ist oder aus anderen Objekten/Datentypen? Mich interessiert vor allem die Betrachtung des Arrays als ein mathematischer Vektor (daher hier im Beipiel auch double ). Ich persönlich finde die Varianten 2 und 3 "korrekter", da Array-Indizes nunmal nicht negativ sein können, aber dafür sind sie im Quellcode auch unübersichtlicher als die Variante 1. Meine Fragestellung bezieht sich natürlich nicht nur auf for -Schleifen, sondern es könnte auch sein, dass eine Indexvariable irgendwo deklariert wird und dann im Laufe des Programms ihr Wert berechnet wird...

    Wem die Diskussion zu kleinlich ist, bitte raushalten 😋
    Auf die Meinung aller anderen bin ich sehr gespannt. 🙂

    Grüße



  • genaugenommen eigentlich std::ptrdiff_t, da

    \quad\, \tt{vec}[i] = *(\tt{vec} + i) \\ \Rightarrow \tt{\&vec}[i] = \tt{vec} + i \\ \Rightarrow i = \tt{\&vec}[i] - \tt{vec}

    Syntaktisch sind auch negative Werte als Array-Indizes erlaubt:

    double darr[7];
    double* mid = darr+3;
    
    for (std::ptrdiff_t index = -3; index <= +3; ++index)
    {
      std::cout << mid[index] << std::endl;
    }
    


  • Da der Wert im Beispiel des OP von 0 bis 41 läuft ist hier IMO ganz klar size_t angebracht.



  • hustbaer schrieb:

    Da der Wert im Beispiel des OP von 0 bis 41 läuft ist hier IMO ganz klar size_t angebracht.

    Da das Beispiel des OP eben nur ein Beispiel war und er die Frage als rein philosophisches Thema bezüglich Arrays im Allgemeinen in den Raum geworfen hat habe ich einen entsprechenden allgemeinen Typen angegeben - der auch 0-41 abdeckt 🙂



  • Das wird ja sogar noch philosophischer als ich gedacht hatte 😉

    auf std::ptrdiff_t kam ich gar nicht, da ich Indizes noch nie in einem Kontext benutzt habe, in dem sie negativ geworden wären...

    Also sehe ich das richtig, dass ihr es auch bevorzugt z. B. std::size_t zu nehmen, auch wenns dann in mathematisch komplexen Ausdrücken tendenziell ein bisschen unübersichtlicher wird? (Ein int ist halt doch irgendwie rein optisch auf den ersten Blick deutlich als Datentyp zu erkennen (und wenn's nur an dem Syntaxhighlighting liegt, das bei size_t "fehlt").)



  • Bloops schrieb:

    (und wenn's nur an dem Syntaxhighlighting liegt, das bei size_t "fehlt").)

    da muß man den editor halz einstellen, daß er

    size_t
    

    auch blau macht.

    ja, size_t ist am üblichsten. ptr_diff wäre eigtnlich richtiger, aber weil außer pumuckl das keiner weiß, bleibts wohl bei size_t.

    und wenn man das echt nicht mag, ist long besser als int. weils auf dem 64-bitter auch 64-bittig wird, und nicht wie der int kurz bleibt.



  • long ist unter x64-MSVC immer noch 32-bittig



  • Wenn man Dinge zählt die in den Speicher passen, und es per Definition nicht negativ werden kann, dann finde ich size_t "richtiger" als ptrdiff_t.



  • hustbaer schrieb:

    Wenn man Dinge zählt die in den Speicher passen, und es per Definition nicht negativ werden kann, dann finde ich size_t "richtiger" als ptrdiff_t.

    also size_t für größenangaben und ptr_diff für indizes. sagen wir ja.
    wo ist das problem?



  • Angenommen, addressierbar wären 2 bytes (CHAR_BIT = 1), dann würde der Ausdruck 0[2] auf das 2. Byte zeigen (2 wäre ein size_t). Um das 2. Byte mit der gleichen Basisadresse mit einem ptrdiff_t zu adressieren, müsste man 0[-1] nehmen und das sieht "unrichtiger" aus, weil da ein integer underflow auftritt (evtl. undefiniertes Verhalten).

    IRL würde es z.B. auftreten, wenn man ein über 2GiB großes Array/Vector in einem 4GiB Adressraum verwenden möchte.



  • @volkard:
    Garkein Problem. Und natürlich auch size_t für Indizes, wenn diese nie negativ werden können, und sich auf Dinge beziehen die in den Speicher passen (also nicht Offsets in Files o.ä.).

    @Superlexx:
    Den Fall kann man leicht verhindern indem man sicherstellt dass man nie ein Stück das >= 50% des (adressierbaren) Hauptspeichers ist anfordern kann. Bzw. dass das Programm es garnicht erst versucht.


Anmelden zum Antworten