Является ли sizeof (некоторый указатель) всегда равным четырем?

Например: sizeof(char*) возвращает 4. Как и int*, long long*, все, что я пробовал. Есть ли исключения из этого?

Ответ 1

Гарантией, которую вы получаете, является sizeof(char) == 1. Нет других гарантий, в том числе нет гарантии, что sizeof(int *) == sizeof(double *).

На практике указатели будут размером 2 в 16-разрядной системе (если вы можете ее найти), 4 в 32-битной системе и 8 в 64-битной системе, но ничего не получится в использовании на заданный размер.

Ответ 2

Даже на простой 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 С++ 2008 я получаю 4, 12 и 8 для размеров указателей на функцию-член.

Раймонд Чен говорил об этом здесь.

Ответ 3

Еще одно исключение из уже опубликованного списка. На 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-разрядных сегментов

Ответ 4

если вы компилируете для 64-разрядной машины, тогда это может быть 8.

Ответ 5

Технически говоря, стандарт C гарантирует, что sizeof (char) == 1, а остальная часть - до реализации. Но на современных архитектурах x86 (например, чипы Intel/AMD) это довольно предсказуемо.

Вероятно, вы слышали, что процессоры описываются как 16-разрядные, 32-разрядные, 64-разрядные и т.д. Это обычно означает, что процессор использует N-биты для целых чисел. Поскольку указатели хранят адреса памяти, а адреса памяти - целые числа, это эффективно говорит вам, сколько бит будет использоваться для указателей. sizeof обычно измеряется в байтах, поэтому код, скомпилированный для 32-разрядных процессоров, будет сообщать размер указателей 4 (32 бит /8 бит на каждый байт), а код для 64-разрядных процессоров будет сообщать размер указателей 8 (64 бит /8 бит на байт). В этом случае ограничение на 4 ГБ ОЗУ для 32-разрядных процессоров происходит из - если каждый адрес памяти соответствует байту, для обращения к большему количеству памяти вам нужны целые числа, превышающие 32 бит.

Ответ 6

В дополнение к различиям 16/32/64 бит могут возникать даже более сложные вещи.

Были машины, где sizeof (int *) будет одним значением, вероятно 4, но где sizeof (char *) больше. Машины, которые, естественно, обращаются к словам вместо байтов, должны "увеличивать" указатели на символы, чтобы указать, какую часть слова вы действительно хотите, чтобы правильно реализовать стандарт C/С++.

Это сейчас очень необычно, поскольку разработчики аппаратного обеспечения узнали значение адресной адресации байтов.

Ответ 7

Размер указателя в основном зависит от архитектуры системы, в которой он реализован. Например, размер указателя в 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-битной машине.

Ответ 8

8-разрядные и 16-разрядные указатели используются в большинстве низкопрофильных микроконтроллеров. Это означает, что каждая стиральная машина, микро, холодильник, старые телевизоры и даже автомобили.

Вы могли бы сказать, что это не имеет никакого отношения к программированию на реальном мире. Но вот один реальный пример: Arduino с 1-2-4 кГц (в зависимости от чипа) с 2 байтовыми указателями.

Это недавнее, дешевое, доступное для всех и достойное кодирование.

Ответ 9

В дополнение к тому, что люди говорили о 64-битных (или каких-либо) системах, существуют другие типы указателей, кроме указателя на объект.

Указатель на член может быть почти любого размера, в зависимости от того, как они реализованы вашим компилятором: они не обязательно имеют одинаковый размер. Попробуйте указатель на член класса POD, а затем указатель на элемент, унаследованный от одного из базовых классов класса с несколькими базами. Какая радость.

Ответ 10

Из того, что я помню, он основывался на размере адреса памяти. Таким образом, в системе с 32-разрядной адресной схемой sizeof вернет 4, так как это 4 байта.

Ответ 11

В общем случае sizeof (почти все) изменится при компиляции на разных платформах. На 32-битной платформе указатели всегда одного размера. На других платформах (пример 64 бит является очевидным) это может измениться.

Ответ 12

Нет, размер указателя может меняться в зависимости от архитектуры. Существует множество исключений.

Ответ 13

Размер указателя и int составляет 2 байта в компиляторе Turbo C на 32-битной машине Windows.

Таким образом, размер указателя является специфичным для компилятора. Но, как правило, большинство компиляторов реализованы для поддержки 4-байтовой переменной указателя в 32-битной и 8-байтовой указательной переменной в 64-битной машине).

Таким образом, размер указателя не одинаковый во всех машинах.

Ответ 14

В 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.

Ответ 15

Причина, по которой размер вашего указателя составляет 4 байта, заключается в том, что вы компилируете 32-битную архитектуру. Как отметил Фрай Гуй, в 64-битной архитектуре вы увидите 8.

Ответ 16

Указатель - это просто контейнер для адреса. На 32-битной машине ваш диапазон адресов составляет 32 бита, поэтому указатель всегда будет 4 байта. На 64-битной машине у вас был диапазон адресов из 64 бит, указатель будет 8 байтов.

Ответ 17

Для полноты и исторического интереса в 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

Источник: fooobar.com/questions/34259/...

Ответ 18

Он всегда будет равен sizeof size_t.

На 32-битных машинах это, как правило, 4. На 64-битных машинах это имеет значение 8.