Наприклад:
sizeof(char*)
повертає 4. Як же int*
, long long*
все , що я пробував. Чи є з цього винятки?
Наприклад:
sizeof(char*)
повертає 4. Як же int*
, long long*
все , що я пробував. Чи є з цього винятки?
Відповіді:
Гарантія, яку ви отримуєте, така sizeof(char) == 1
. Інших гарантій немає, в тому числі немає жодних гарантій sizeof(int *) == sizeof(double *)
.
На практиці покажчики будуть розміром 2 для 16-бітної системи (якщо ви знайдете її), 4 для 32-бітної системи та 8 для 64-бітної системи, але нічого не можна отримати, спираючись на задану розмір.
Навіть на звичайній 32-бітній платформі x86 ви можете отримати різні розміри вказівників, спробуйте це для прикладу:
struct A {};
struct B : virtual public A {};
struct C {};
struct D : public A, public C {};
int main()
{
cout << "A:" << sizeof(void (A::*)()) << endl;
cout << "B:" << sizeof(void (B::*)()) << endl;
cout << "D:" << sizeof(void (D::*)()) << endl;
}
Під Visual C ++ 2008 я отримую 4, 12 та 8 для розмірів функції покажчиків на член.
Реймонд Чен розповів про це тут .
Ще один виняток із вже опублікованого списку. На 32-бітних платформах вказівники можуть приймати 6, а не 4 байти:
#include <stdio.h>
#include <stdlib.h>
int main() {
char far* ptr; // note that this is a far pointer
printf( "%d\n", sizeof( ptr));
return EXIT_SUCCESS;
}
Якщо скласти цю програму з Open Watcom і запустити її, ви отримаєте 6, тому що далеко вказівники, які вона підтримує, складаються з 32-бітного зміщення та 16-бітного значення сегмента
якщо ви збираєте для 64-бітної машини, то це може бути 8.
sizeof(char*)==1
,? Ти впевнений? Ви не маєте на увазі size(char)==1
?
Технічно кажучи, стандарт C гарантує лише, що розмір (char) == 1, а решта залежить від реалізації. Але в сучасних архітектурах x86 (наприклад, мікросхеми Intel / AMD) це досить передбачувано.
Напевно, ви чули процесори, описані як 16-бітні, 32-розрядні, 64-бітні тощо. Це зазвичай означає, що процесор використовує N-біти для цілих чисел. Оскільки вказівники зберігають адреси пам’яті, а адреси пам’яті цілі числа, це ефективно говорить про те, скільки бітів буде використано для покажчиків. sizeof зазвичай вимірюється в байтах, тому код, складений для 32-розрядних процесорів, повідомляє розмір покажчиків, який буде 4 (32 біта / 8 біт на байт), а код для 64-розрядних процесорів повідомляє, що розмір покажчиків становить 8 (64 біта / 8 біт на байт). Звідси випливає обмеження 4 Гб оперативної пам’яті для 32-бітних процесорів - якщо кожна адреса пам’яті відповідає байту, для адреси більшої кількості пам’яті вам потрібні цілі числа, що перевищують 32-бітні.
Розмір покажчика в основному залежить від архітектури системи, в якій він реалізований. Наприклад, розмір вказівника в 32 бітах становить 4 байти (32 біт) і 8 байт (64 біт) у 64 бітових машинах. Типи бітів у машині - це не що інше, як адресу пам'яті, яку вона може мати. 32-бітні машини можуть мати 2^32
адресний простір, а 64-бітні машини можуть мати 2^64
адресний простір. Отже, вказівник (змінна, яка вказує на місце пам'яті) повинен мати можливість вказувати на будь-яку адресу пам'яті (2^32 for 32 bit and 2^64 for 64 bit
), яку має машина.
Через цю причину ми бачимо, що розмір вказівника має бути 4 байти в 32-бітній машині та 8 байт у 64-бітній машині.
На додаток до 16/32/64 бітових відмінностей можуть виникати навіть більш дивні речі.
Були машини, де sizeof (int *) буде одним значенням, ймовірно, 4, але де sizeof (char *) більший. Машини, які природно звертаються до слів замість байтів, повинні "збільшувати" символьні вказівники, щоб вказати, яку частину слова ви дійсно хочете, щоб правильно реалізувати стандарт C / C ++.
Це зараз дуже незвично, оскільки дизайнери апаратних засобів дізналися значення адресності байтів.
void*
і char*
обробляються програмним забезпеченням і доповнюються 3-бітовим зміщенням у слові - але оскільки насправді не існує 64-бітного адресного простору, зміщення зберігається у 3-бітовому 64-бітному порядку високого порядку слово. Так char*
і int*
мають однаковий розмір, але мають різні внутрішні уявлення - і код , який передбачає , що покажчики «справді» тільки цілі числа , може відбутися збій.
8-бітний та 16-бітний покажчики використовуються в більшості низькопрофільних мікроконтролерів. Це означає, що кожна пральна машина, мікро, холодильник, старі телевізори і навіть машини.
Можна сказати, що це не має нічого спільного з програмуванням у реальному світі. Але ось один реальний приклад світу: Arduino з 1-2-4k таран (залежно від мікросхеми) з 2-х байт-покажчиками.
Це недавнє, дешеве, доступне для всіх і вартує кодування.
На додаток до того, що люди говорили про 64-бітні (або будь-які інші) системи, існують і інші види покажчика, ніж вказівник на об’єкт.
Вказівник на члена може бути майже будь-якого розміру, залежно від того, як їх реалізує ваш компілятор: вони не обов'язково навіть усі однакового розміру. Спробуйте вказівник на члена класу POD, а потім вказівник на члена, успадкований від одного з базових класів класу з декількома базами. Що весело.
Як я пам’ятаю, це ґрунтується на розмірі адреси пам’яті. Отже, у системі з 32-бітовою схемою адреси sizeof поверне 4, оскільки це 4 байти.
sizeof (unsigned int) == sizeof (signed int)
ця вимога міститься в 3.9.1 / 3. «Для кожного з стандарту , підписаного цілим числом типів, існує відповідне (але різний) стандартний беззнаковий цілий типу: unsigned char
, unsigned short int
, unsigned int
, unsigned long int
, і unsigned long long int
, кожен з яких займає таку ж кількість зберігання і має той же вимога до вирівнювання як відповідні знакової цілому типу "
Ні, розмір вказівника може змінюватися в залежності від архітектури. Є численні винятки.
Розмір покажчика та int - 2 байти у компіляторі Turbo C на 32-бітній машині Windows.
Отже, розмір вказівника залежить від компілятора. Але зазвичай більшість компіляторів реалізовані для підтримки 4-байтної змінної вказівника в 32-бітовій та 8-байтної змінної вказівника в 64-бітній машині).
Отже розмір вказівника не однаковий у всіх машинах.
Причина, що розмір вказівника становить 4 байти, полягає в тому, що ви збираєте для 32-бітної архітектури. Як зазначав FryGuy, на 64-бітній архітектурі ви побачите 8.
У Win64 (Cygwin GCC 5.4) давайте подивимось наступний приклад:
Спочатку випробуйте таку структуру:
struct list_node{
int a;
list_node* prev;
list_node* next;
};
struct test_struc{
char a, b;
};
Код тестування нижче:
std::cout<<"sizeof(int): "<<sizeof(int)<<std::endl;
std::cout<<"sizeof(int*): "<<sizeof(int*)<<std::endl;
std::cout<<std::endl;
std::cout<<"sizeof(double): "<<sizeof(double)<<std::endl;
std::cout<<"sizeof(double*): "<<sizeof(double*)<<std::endl;
std::cout<<std::endl;
std::cout<<"sizeof(list_node): "<<sizeof(list_node)<<std::endl;
std::cout<<"sizeof(list_node*): "<<sizeof(list_node*)<<std::endl;
std::cout<<std::endl;
std::cout<<"sizeof(test_struc): "<<sizeof(test_struc)<<std::endl;
std::cout<<"sizeof(test_struc*): "<<sizeof(test_struc*)<<std::endl;
Вихід нижче:
sizeof(int): 4
sizeof(int*): 8
sizeof(double): 8
sizeof(double*): 8
sizeof(list_node): 24
sizeof(list_node*): 8
sizeof(test_struc): 2
sizeof(test_struc*): 8
Ви можете бачити, що в 64-розрядному, sizeof(pointer)
є 8
.
Вказівник - це лише контейнер для адреси. На 32-бітовій машині діапазон адрес становить 32 біти, тому вказівник завжди буде 4 байти. Якщо на 64-бітовій машині у вас був діапазон адрес 64 біт, покажчик буде 8 байт.
Тільки для повноти та історичного інтересу у 64-бітовому світі існували різні конвенції платформ за розмірами довгих та довгих типів, названі LLP64 та LP64, головним чином між системами типу Unix та Windows. Старий стандарт на ім'я ILP64 також зробив int = 64-розрядний.
Microsoft підтримувала LLP64, де longlong = 64 біт шириною, але довго залишався на рівні 32, щоб полегшити перенесення.
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