2012-04-06 10 views
5

Sehr einfache Fragen Jungs, aber vielleicht vergesse ich nur etwas. In 64-Bit-Linux ist eine lange 8 Bytes korrekt? Wenn das der Fall ist, und ich möchte das 64th Bit setzen, kann ich wie folgt vorgehen:Lange Art 64bit Linux

unsigned long num = 1<<63; 

Jedes Mal, wenn ich diese kompilieren, aber es gibt mir eine Fehlermeldung, dass ich mehr als links verschoben die Breite. Auch wenn ich die ersten 32 Bit eines langen Typ (ohne Vorzeichen) nehmen wollte, kann ich tun:

num = num&0xFFFFFFFF; 

oder was ist:

num = (int)(num); 

Danke.

+5

Versuchen: 'unsigned long num = 1UL << 63;' – Mysticial

+0

@Mysticial Warum nicht schreiben, dass als eine Antwort zusammen mit der ganzen Zahl Förderung Sachen? – cnicutar

+1

Hängt davon ab, welcher Compiler verwendet wird. Viele Legacy-Compiler würden standardmäßig 32 Bit lang sein, selbst wenn sie auf einer 64-Bit-Maschine laufen. Bestätigen Sie, dass "sizeof num" 8 ist, bevor Sie etwas mehr versuchen. – wallyk

Antwort

3

In 64-Bit-Linux ist eine lange 8 Bytes korrekt?

Muss nicht sein. Hängt vom Compiler ab als vom zugrunde liegenden Betriebssystem. Überprüfen Sie dies für eine nette Diskussion. What decides the sizeof an integer?

Jedes Mal, wenn ich diese kompilieren, aber es mir einen Fehler gibt, dass ich bin links um mehr als die Breite Verschiebung

Jeder dies bereits beantwortet hat. Verwenden Sie 1UL

Auch wenn ich die ersten 32 Bit eines lange Typ (ohne Vorzeichenerweiterung) nehmen wollte, kann ich tun:

num = num&0xFFFFFFFF; 
or what about: 

num = (int)(num); 

num = num&0xFFFFFFFF. Dies wird Ihnen die unteren 32 Bits geben. Aber beachten Sie, dass, wenn long ist nur 4 Bytes auf Ihrem System, dann erhalten Sie die gesamte Nummer. Kommen Sie zum Zeichenerweiterungsteil, wenn Sie eine long und nicht unsigned long verwendet haben, dann können Sie die vorzeichenerweiterten Bits nicht beseitigen. Zum Beispiel wird -1 als alle Einsen dargestellt, direkt vom 0. Bit. Wie werden Sie diese durch Maskieren vermeiden?

num = (int)(num) geben Ihnen die unteren 32-Bits, aber Compiler könnte durch eine Überlaufausnahme Warnung, wenn num nicht in einen Code int

+0

Stimmen Sie zu, dass C "long" keine 64 Bits auf 64-Bit-Maschine vorgibt. Allerdings implicitely Linux dies. Sehen Sie sich einfach alle Zeiger an, die durch "unsigned long" und Speicher-Offsets, die durch "signed long" (z. B. syscalls) weitergeleitet wurden, weitergeleitet wurden. Solange also der Linux-Quellcode sich nicht drastisch ändert, würde ich ** ja ** auf die Frage antworten: "In 64-Bit-Linux ist ein' long' 8Bytes, richtig? " –

0

Ich glaube, das Problem mit der ersten Frage ist, dass der Compiler '1' als eine ganze Zahl behandelt, nicht als eine lange ganze Zahl. Es merkt es erst nach dem Auftrag.

Sie können das Problem beheben, indem Sie:

unsigned long num = (unsigned long)1<<63; 
+0

Wissen Sie zufällig die Antwort auf den zweiten Teil meiner Frage? Über das Erhalten der ersten 32 Bits ohne Vorzeichenerweiterung? Würde ich etwas Ähnliches wie num = num & (unsigned long) (0xFFFFFFFF) machen? – de1337ed

+0

@ de1337ed Ich habe den zweiten Teil Ihrer Qn beantwortet. Auschecken –

4

Eigentlich, wenn Sie einige genaue Länge (in Bits) wollen für Ihre ganze Zahlen, ein C99 konformen Compiler unter der Annahme, #include <stdint.h> und Typen verwenden wie int64_t, int32_t usw. eine praktische Art ist intptr_t, ein integer-Typ mit der gleichen Anzahl von Bits wie void* Zeiger (so dass Sie es sich um eine Maschine „Wort“ nennen kann)

+1

Ein C99-konformer Compiler muss keine Typen mit fester Breite bereitstellen, z. 'int64_t'. Nur Zweierkomplement-Implementierungen, die 8-, 16-, 32- und 64-Bit-Integertypen ohne Padding-Bits bereitstellen, sind * erforderlich *, um Indextypen mit fester Breite in 'stdint.h' bereitzustellen. – dreamlax

1

Für Portabilität Sie nutzen könnten:

limits.h

#define LNG_BIT (sizeof(long) * CHAR_BIT) 

unsigned long num = 1UL << (LNG_BIT - 1); 

Um "niedrig int", so etwas wie ?:

#define INT_BIT (sizeof(int) * CHAR_BIT) 

if (LNG_BIT > INT_BIT) 
    return num & (~0UL >> INT_BIT); 
else 
    return num; 

oder

num &= ~(~0U << INT_BIT); 

Oder verwenden Sie Maske, etc. Kommt darauf an, warum, für was usw. Sie wollen die int Bits.

Beachten Sie auch die Optionen von Compilern; I.e. wenn Sie gcc verwenden:

-m32
-m64
-mx32
        generieren Code für einen 32-Bit- oder 64-Bit-Umgebung
        * Die Option -m32 legt Int, Long und Pointer-Typen auf 32 Bit fest und generiert Code, der auf einem beliebigen i386-System ausgeführt wird.
        * Die Option -m64 setzt Int auf 32 Bit und Long und Zeigertypen auf 64 Bit und generiert Code für die x86-64-Architektur. Für Darwin werden nur die Optionen -fno-pic und -mdynamic-no-pic deaktiviert.
        * Die -mx32 Option setzt int, lang, und Zeigertypen zu 32 Bits und erzeugt einen Code für die x86-64 Architektur.

Es gibt auch -maddress-mode=long usw.

-maddress-mode = lange
        Code generiert für langen Adressmodus. Dies wird nur für 64-Bit- und x32-Umgebungen unterstützt. Dies ist der Standardadressmodus für 64-Bit-Umgebungen.

0

AFAIR passt wie dies die Quelle eines großen Fehlers in ReiserFS vor ein paar Jahren war :

ein langer, ja, das ist 64-Bit und auf den meisten anderen 64-Bit-linux-plytforms zu
unsigned long num = 1<<63; 

Wenn Sie x86_64 sprechen.Das Problem ist, dass sowohl die 1 als auch die 63 in Ihrem Code sind einfach int, und so ist das Ergebnis undefiniert. Besser nutzen

unsigned long num = 1UL<<63; 

oder

unsigned long num = (unsigned long)1<<63; 
Verwandte Themen