2016-12-19 4 views
2

Beim Versuch, einen Vektor mit unbekannten großen Werten zu erhalten, kam ich auf eine Lösung, die ich für völlig falsch hielt: Ich vermute, wenn ein Element der std::vector<size_t> zuerst einem kleinen Wert zugeordnet wird und dann einem großen, könnte ein Fehler vorliegen oder Datenverlust, weil der Typ für den gesamten Vektor bereits festgelegt wurde und etwas Speicherplatz im Speicher angeordnet wurde.Ist es immer sicher, std :: vector mit verschiedenen Integer-Typen zu verwenden?

jedoch der folgende Code funktioniert:

#include<vector> 
#include<iostream> 
#include<typeinfo> 

int main(){ 

    std::vector<size_t> vec; 

    // Fixing size and adding small number which 
    // I suppose would set type as a small one, 
    // i.e. int 
    vec.resize(2); 
    int i = 0; 
    std::fill(vec.begin(),vec.end(),i);  

    // add a big number that should not fit smaller type 
    unsigned long long bignum = 18446744073709551614; 
    vec.push_back(bignum); 

    std::cout<<vec[0]<<" "<<vec[1]<<" "<<vec[2]<<std::endl; 
    std::cout<<typeid(vec[0]).name()<<std::endl 
    <<typeid(vec[1]).name()<<std::endl<<typeid(vec[2]).name()<<std::endl; 

    // cell 0 was already initialized with int, trying to make oveflow 
    vec[0] = 18446744073709551613; 

    std::cout<<vec[0]<<" "<<vec[1]<<" "<<vec[2]<<std::endl; 
    std::cout<<typeid(vec[0]).name()<<std::endl 
    <<typeid(vec[1]).name()<<std::endl<<typeid(vec[2]).name()<<std::endl; 

    return 1; 
} 

Allerdings ist der Ausgang nicht Typnamen enthalten, vielleicht wegen meiner Compiler:

$ ./a.out 
0 0 18446744073709551614 
m 
m 
m 
18446744073709551613 0 18446744073709551614 
m 
m 
m 

So ist es sicher für alle Compiler und kann ich frei mit vector::<size_t> arbeiten (an Funktionen senden, usw.), wenn ich die verwendeten Integertypen nicht kenne?

+0

sollte sicher sein. size_t ist eigentlich uint32_t oder uint64_t oder sogar uint16_t hängt von der Zielrechnerarchitektur ab. –

Antwort

3

vector<size_t> bedeutet ein Vektor, dessen Einträge alle size_t sind. Wenn Sie versuchen, einen Wert zu speichern, der kein size_t ist, wird es vor dem Speichern implizit in size_t konvertiert. Dies könnte einen Datenverlust bedeuten, wenn der ursprüngliche Wert eine Ganzzahl außerhalb des Bereichs von [0, SIZE_MAX] war.

Ihre Frage schlägt vor, dass Sie sich vorstellen, dass der Vektor Objekte verschiedener Typen speichert, aber das passiert nicht.

Hinweis: size_t steht normalerweise für die Größe der größtmöglichen zuweisbaren Einheit. Vielleicht wäre es besser, einen Typ zu verwenden, der die Quelle der Werte, die Sie speichern, z. uint64_t.

+0

Danke! Sieht so aus, als hätte ich gerade alles falsch verstanden, weil ich folgendes dachte: _Der Typ size_t ist der vorzeichenlose Integer-Typ, der das Ergebnis des Operators sizeof (und des Operators offsetof) ist, so dass er garantiert groß genug ist, um ihn zu enthalten Größe des größten Objekts, das Ihr System verarbeiten kann (z. B. ein statisches Array von 8 GB). Der Typ size_t kann größer als, gleich oder kleiner als ein unsigned int sein, und Ihr Compiler könnte zur Optimierung Annahmen darüber machen. "_ Bedeutet, dass' size_t' die Größe der Variablen anpasst, um das Ergebnis zu enthalten. Aber es ist nur ein Geben Sie – Slowpoke

+1

@Slowpoke Ich sehe nicht, wie Sie "size_t adjests variable size" aus dem zitierten Text. * Verschiedene Systeme * können unterschiedliche Größen von size_t haben, aber es ändert sich nicht während eines Programmlaufs –

+0

Ja, sorry, Ich habe das schon vor einiger Zeit falsch verstanden und glaubte, dass sizeof irgendwie angewendet wurde, um Variablen so zu machen, dass sie die Daten enthalten. – Slowpoke

3

Nein, es ist nicht sicher.

Es funktioniert nur, weil Sie eine int >= 0 setzen. size_t ist unsigned Wenn Sie also versuchen, einen negativen Wert einzugeben, wird negative_value % 2**n angezeigt, wobei n die Anzahl der Bits angibt, die für den Typ ohne Vorzeichen verwendet werden.


Das Element in Ihrem Vektor sind size_t. Wenn Sie es mit i füllen, bitten Sie den Compiler, eine int in eine size_t zu werfen. Dies ist nicht "sicher".


vec[0] = 18446744073709551613; 

Und hier ist das sicher, weil vec [0] ein size_t ist.


Beachten Sie, dass size_t ist so konzipiert ... Größe zu handhaben. Daher ist der Maximalwert, der mit size_t umgehen kann, nicht behoben. Wenn Sie eine ganze Zahl haben wollen. Verwenden Sie <cstdint>.

+0

Setzen Sie einen negativen Wert auf unsigned int hat kein undefiniertes Verhalten. –

+0

@DUJiaen Meine schlechte, ich dachte, dass es wie C war. Aber es ist auch nicht "sicher". – Stargateur

3

Zusätzlich zu der Antwort von @Stargateur ist die beste portable Wette intmax_t und uintmax_t. Sie sind garantiert die größten Integer-Typen auf der Plattform.

Möglicherweise gibt es auch Compiler spezifische Erweiterungen wie __int128_t. This answer gibt einige Informationen über 128-Bit-Builtins im gcc. Beachten Sie, dass std::intmax_t 64 Bit sein wird.

+0

gcc liefert normalerweise 'intmax_t' als 64-bit und' int128_t' als 128-bit Integer-Typen (entspricht nicht dem Standard) –

+0

@MM, OP hat keinen Compiler angegeben, aber danke, ich werde eine Notiz hinzufügen dass es Compiler spezifische Erweiterungen geben könnte – Incomputable

Verwandte Themen