Який розмір бітів long у 64-розрядних Windows?


137

Не так давно хтось сказав мені, що longце не 64 біти на 64-бітних машинах, і я завжди повинен користуватися int. Це для мене не мало сенсу. Я бачив, як документи (наприклад, офіційний на офіційному сайті Apple) говорять, що longце дійсно 64 біти при компіляції для 64-бітного процесора. Я подивився, що це було в 64-бітних Windows, і виявив

  • Windows: longі intзалишається 32-бітовою довжиною, а для 64-бітних цілих чисел визначені нові спеціальні типи даних.

(від http://www.intel.com/cd/ids/developer/asmo-na/eng/197664.htm?page=2 )

Що я повинен використовувати? Чи слід визначити щось на зразок uw, sw((не) підписану ширину) як longякщо ні, то в Windows, інакше зробити перевірку цільового біта процесора?


У Windows з MSVC ++ int і long є 32-розрядні: msdn.microsoft.com/en-us/library/3b2e7499.aspx . Однак, щоб наприклад вектори могли зберігати більше 4G елементів, розмір_t - 64 біт. Тому потрібно використовувати int64_t замість int для ітерації, наприклад, вектори, які можуть містити більше 4G елементів.
Серж Рогач


@SergeRogatch вони повинні використовувати size_tабо тип ітератора ітерацію, а НЕ intабоint64_t
phuclv

2
@ LưuVĩnhPhúc, коли size_tвін стає хитрим біля від’ємних чисел, тому що він size_tне підписаний. Так for(size_t i=0; i<v.size()-2; i++)не виконується для вектора розміру 0 і 1. Інший приклад: for(size_t i=v.size()-1; i>=0; i--).
Серж Рогач

2
Якщо ви займаєтесь математикою за покажчиками (тобто зі size_tзначеннями, результат слід зберігати в змінній ptrdiff_tтипу - яка призначена для того, щоб бути достатньо великою, щоб утримати такий результат і є підписаним типом саме з цієї причини!)
SlySven

Відповіді:


261

У світі Unix було декілька можливих механізмів розмірів цілих чисел та покажчиків для 64-бітних платформ. Два з найбільш широко використовуваних - ILP64 (насправді, лише небагато прикладів цього; Cray був одним з таких) та LP64 (майже для всього іншого). Скорочення походять від "int, long, вказівники 64-бітні" та "long, вказівники 64-розрядні".

Type           ILP64   LP64   LLP64
char              8      8       8
short            16     16      16
int              64     32      32
long             64     64      32
long long        64     64      64
pointer          64     64      64

Система ILP64 була відмовлена ​​на користь LP64 (тобто майже всі пізніші учасники використовували LP64, виходячи з рекомендацій групи Аспен; лише системи з довгим спадком 64-бітної роботи використовують іншу схему). Усі сучасні 64-бітні системи Unix використовують LP64. MacOS X і Linux - це сучасні 64-бітні системи.

Microsoft використовує іншу схему для переходу на 64-бітну: LLP64 ("long long, покажчики - 64-бітні"). Це має перевагу в тому, що 32-розрядне програмне забезпечення можна перекомпілювати без змін. Він має дефіцит того, що він відрізняється від того, що роблять всі інші, а також вимагає перегляду коду для використання 64-бітових ємностей. Завжди була необхідна ревізія; це був лише інший набір змін, необхідних на платформах Unix.

Якщо ви розробляєте програмне забезпечення на основі імен типу цілочисельних типів, нейтральних для платформи, ймовірно, використовуючи <inttypes.h>заголовок C99 , який, коли типи доступні на платформі, надає підписані (перелічені) та непідписані (не вказані; префікс з 'u'):

  • int8_t - 8-бітні цілі числа
  • int16_t - 16-бітні цілі числа
  • int32_t - 32-бітні цілі числа
  • int64_t - 64-бітні цілі числа
  • uintptr_t - непідписані цілі числа, досить великі, щоб утримувати покажчики
  • intmax_t- найбільший розмір цілого числа на платформі (може бути більшим, ніж int64_t)

Потім ви можете кодувати свою програму, використовуючи ці типи, де це важливо, і бути дуже обережним із типами системи (які можуть бути різними). Є intptr_tтип - цілий цільовий тип, що підписується, для проведення покажчиків; вам слід планувати не використовувати його або використовувати його лише як результат віднімання двох uintptr_tзначень (ptrdiff_t ).

Але, як зазначається в питанні (з невірою), на 64-бітних машинах існують різні системи для розмірів цілих типів даних. Звикнути; світ не збирається змінюватися.


12
Для тих, хто користується досить довго, 64-бітний перехід має деякі паралелі з 16-бітним 32-бітовим переходом середини 80-х. Були комп'ютери IL32 та інші, які були L32 (адаптуючи нове позначення до старої проблеми). Іноді "int" був 16-розрядним, іноді 32-розрядним.
Джонатан Леффлер

4
Не забувайте, що це стосується лише мов C-ish. Інші мають більш специфічні вимоги, коли: а) автору компілятора заборонено вибирати розмір типових даних безвільно або б) фізичне представлення типів даних не "протікає" або в) цілі числа завжди нескінченно великі.
Йорг W Міттаг

2
Правда - але для тих мов, які визначають поведінку, в першу чергу це не проблема. Наприклад, у Java є "довгий", але розмір фіксований (64-бітний?) На всіх платформах. Отже, немає жодної проблеми з перенесенням на 64-бітну машину; розмір не змінюється.
Джонатан Леффлер

17
@TomFobear: ILP64 представляє одне головне питання - як ви називаєте 32-бітний тип? Або якщо ви називаєте 32-розрядний тип short, як ви називаєте 16-бітний тип? І якщо ви називаєте 16-розрядний тип charдля UTF-16 тощо, як ви називаєте 8-бітний тип? Отже, використовуючи LP64, ви залишаєте 8-бітну char, 16-бітну short, 32-бітну int, 64-бітну long, з можливістю розширення вгору до 128-бітової, long longколи (якщо?) Це стане актуальним. Після цього у вас є більше потужностей 256, ніж у вас є імена на C (ну, я думаю, у вас могло бути 256-бітове intmax_t, і лише тоді у вас закінчується). Є заслуга до LP64.
Джонатан Леффлер

2
Можливо, це очевидно для вас, хлопці, але я думаю, що варто відзначити, що C # використовує різні цілі розміри від усього іншого. Нещодавно у мене виникла взаємодія з DLL, оскільки C # використовує 64-бітні тривалості ( msdn.microsoft.com/en-us/library/ms173105.aspx ).
Compholio

57

Незрозуміло, чи йдеться про компілятор Microsoft C ++ або API API. Однак тегу [c ++] немає, тому я припускаю, що мова йде про API Windows. Деякі відповіді постраждали від гниття посилань, тому я надаю ще одне посилання, яке може загнивати.


Для отримання інформації про такі типи API Windows, як INTі LONGт.д., існує сторінка в MSDN:

Типи даних Windows

Інформація також доступна в різних файлах заголовків Windows, таких як WinDef.h . Я перерахував тут кілька релевантних типів:

Тип | S / U | x86 | x64
---------------------------- + ----- + -------- + ------ -
БЮТЕ, БУЛІАН | U | 8 біт | 8 біт
---------------------------- + ----- + -------- + ------ -
КОРОТКА | S | 16 біт | 16 біт
USHORT, WORD | U | 16 біт | 16 біт
---------------------------- + ----- + -------- + ------ -
INT, LONG | S | 32 біт | 32 біт
UINT, ULONG, DWORD | U | 32 біт | 32 біт
---------------------------- + ----- + -------- + ------ -
INT_PTR, LONG_PTR, LPARAM | S | 32 біт | 64 біт
UINT_PTR, ULONG_PTR, WPARAM | U | 32 біт | 64 біт
---------------------------- + ----- + -------- + ------ -
LONGLONG | S | 64 біт | 64 біт
ULONGLONG, QWORD | U | 64 біт | 64 біт

Стовпець "S / U" позначає підписаний / непідписаний.


4

У цій статті про MSDN посилаються на ряд псевдонімів типів (доступних у Windows), які є дещо чіткішими щодо їх ширини:

http://msdn.microsoft.com/en-us/library/aa505945.aspx

Наприклад, хоча ви можете використовувати ULONGLONG для посилання на 64-бітове непідписане цілісне значення, ви також можете використовувати UINT64. (Те саме стосується ULONG та UINT32.) Можливо, це буде трохи зрозуміліше?


1
Чи є гарантія, що uint32_t та DWORD будуть взаємозамінними? Не важко уявити, що їх може не бути [наприклад, якщо перший є 32-розрядним, intа другий 32-розрядним long, gcc припускає, що вказівник на один тип не зможе псевдоніміти другий, незважаючи на відповідність їх представлень].
supercat


2

Найпростіший спосіб познайомитися з цим для вашого компілятора / платформи:

#include <iostream>

int main() {
  std::cout << sizeof(long)*8 << std::endl;
}

Множення на 8 - це отримання бітів з байтів.

Коли вам потрібен певний розмір, найчастіше найпростіше використовувати один із заздалегідь визначених типів бібліотеки. Якщо це небажано, ви можете робити те, що часто відбувається з програмним забезпеченням autoconf, і система конфігурації визначає потрібний тип потрібного розміру.


4
Це не важливо, але 8-бітні байти насправді не є частиною специфікації C (п. 3.6 та 5.2.4.2.1 стандарту C). Хоча вам буде важко знайти машину, де її не було 8 біт, ви можете перевірити LONG_BIT, щоб побачити, наскільки великий ваш довгий тип даних.
Андрес

Звичайно, ви праві, це насправді залежить від архітектури ("адресна одиниця зберігання даних досить велика, щоб вмістити будь-якого члена основного набору символів середовища виконання"), але найбільш часто використовувані архітектури дорівнюють 8 біт.
Пол де Вріезе

Але ОП не запитував про його упорядника / платформу; він запитав конкретно про 64-бітну Windows - імовірно, тому, що він не має зручного доступу до 64-бітної системи Windows для перевірки.
Квомплусон

0

Розмір у бітах longна платформах Windows становить 32 біти (4 байти).

Ви можете перевірити це за допомогою sizeof(long).


-2

Якщо вам потрібно використовувати цілі числа певної довжини, вам, ймовірно, слід скористатися деякими незалежними заголовками платформи, щоб допомогти вам. Підвищення - це гарне місце для погляду.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.