2015-09-30 8 views
2

Дополнительный вопрос (1 балл): Предположим, мы используем 32-разрядные операционные системы Windows и C/C++. Пожалуйста, оцените SizeOf() для следующим образом (единица измерения: байт)Объяснение sizeof() с различными типами данных в C++

• char str[] = “Hello” ; 
• char *p = str ; 
• int n = 10; 
Please calculate: 
• sizeof (str) = __________ 
• sizeof (p) = __________ 
• sizeof (n) = __________ 

Здравствуйте все,

Я пытаюсь обернуть свой ум вокруг этого довольно фундаментальное понятие в C++. Я скажу вам, что я думаю, что правильные ответы - это увидеть, правильно ли я нахожусь на правильном пути. Для первого, sizeof (str), я считаю, что это всего 6 байт. Я заметил шаблон из других проблем, что к этим типам строк добавлен 1 байт. (5 букв +1). Мой вопрос: что это за «+1»? Что касается второго, это просто относится к размеру указателя, p, правильно? который всегда равен 4 байтам? Наконец, третий, я считаю, просто имеет в виду размер int, n. Из чего я знаю, что все ints имеют размер 4 байта правильно? Означает ли это, что все int имеют 4 байта, независимо от того, являются ли они 10 или 10000 или любым другим числом. Любая другая важная информация по этой теме также очень ценится и принимается с распростертыми объятиями! Благодаря!

+0

Во-первых, 6. Последние два зависят от реализации. – Lingxi

+0

Для 32-разрядных Windows оба указателя и указатели имеют 4 байта. – 1201ProgramAlarm

ответ

0

Я заметил шаблон из других проблем, который всегда содержит 1 байт , добавленный к этим типам строк. (5 букв +1). Мой вопрос: что такое ?

Это 1 байт для нулевого завершения, то есть «\ 0». Подумайте об этом.

Если вы используете strlen (вычисляет во время выполнения) вместо sizeof (вычисляет во время компиляции), strlen() начинает сканирование строки с первым символом, увеличивает счетчик, переходит к следующему символу, должен быть некоторый символ на котором строка должна отметить ее конец, правильно? это то, что для нулевого завершения.

От чего я знаю, что все ints имеют размер 4 байта правильно?

В стандарте C++ не указывается размер интегральных типов в байтах, , но он указывает минимальные диапазоны, к которым они должны придерживаться.

Это уже объяснено здесь. [What does the C++ standard state the size of int, long type to be?

Хорошая практика - всегда использовать стандартные определения, чтобы избежать таких путаниц.

Посмотрите в

"stdint.h" или "cstdint"

файлы заголовков, если вы находитесь на Linux. Не уверен в окнах.

int8_t, int16_t, int32_t, uint8_t, uint16_t, uint32_t

это делает код более читаемым.

+1

'sizeof' не сканирует строку для размера. Это постоянная времени компиляции. – 1201ProgramAlarm

+0

изменил его соответствующим образом. – basav

+0

'stdint.h' является стандартным заголовком C. ['cstdint'] (http://en.cppreference.com/w/cpp/header/cstdint) - это заголовок C++, а не' cstdint.h'. – CoffeeandCode

1
char str[] = "Hello" ; 

эквивалентно:

char str[] = {'H', 'e', 'l', 'l', 'o', '\0'}; 

Стандарт гарантирует, что sizeof(char) является 1. Следовательно, sizeof(str) - 6.

Размер указателя и int всегда зависит от платформы.

1

Ok его мой первый ответ на StackOverflow

Первый вопрос:

char str[] = "Hello"; 

в C/C++ символьные массивы нужно нулевое окончание ('\ 0') или (NULL) для идентификации конец массива символов, всякий раз, когда мы читаем массив символов, указатель помещается в первый индекс, и он петли, пока мы не найдем нулевой символ окончания. Его размер равен 6.

Обратите внимание на символ нулевой остановки va ries от компилятора к компилятору (по моим знаниям) вообще используют '\ 0'. вы также можете использовать ноль (0);

char s[] = {'H','E','L','L','O',0}; 

или 'NULL'

char s[] = {'H','E','L','L','O',NULL}; 

Второй вопрос:

char *p = str 

Указатель символ 'P' сохраняет адрес 'ул' символьный массив он указывает первый индекс массива символов и сохраняет адрес. , который имеет 4 байта. следовательно, вы получите

  • sizeof (p) = 4 // p holds the address of str

, где, как если бы вы использовали * р (значение в точке р), то вы получили бы значение, как 1.

• sizeof (*p) = 1 // Now *p is value at p i.e first element in 
       character array = 'H' which is of size 1 byte 

Третий вопрос

int n = 10 

T он, очевидно, собирается дать вам размер 4 байта (8 бит) на 32-битной системе.

Снова размер также варьируется от компилятора к компилятору.

говорить о вашем последнем вопросе

Означает ли это, все Интс 4 байта независимо, если его 10 или 10000, или любое другое число

Ответ да и нет Для 16-битный компилятор C/C++ диапазон для подписанного int - от -32768 до 32767.

Для 32-битного компилятора диапазон -2147483648 до +2147483647

любого числа (типа INT), подписанных между этой областью будет принимать 4 байта на 32 разрядный компилятор, как Turbo C

Любая другая важная информация по этой теме также высоко оценили и приняли с распростертыми объятиями

Интересный факт Для выше, если

int n = 2147483648 //note the extra 1 

по-прежнему будет распечатать или сохранить

2147483647 in n 

Попробуйте (на 32 разрядный компилятор)

Во-вторых в C++ для строк, т.е.

string str = "Hello"; 
• str.size() = 5 // note: its not 6 

Надеюсь, я ответил на ваш вопрос и предоставил дополнительную информацию.

+0

'int n = 2147483648' is Undefined Behavior и может печатать как 2147483647, 2147483648, -2147483647, 0 или' ", вы уволены" или форматируете свой жесткий диск, а не печатаете что-либо. – MSalters

+0

@MSalters Спасибо за указание «Неопределенное поведение», я это запомню. – VoidZero

+0

отличное спасибо за этот очень четкий пробой! – enigma

0

В C++, если мы передаем массив до sizeof, мы получим его длину; а не указатель, который он распадается на размер. Строковый литерал представляет собой массив из n символов с нулевым терминатором.

Так

const char str[] = "foobar"; 

sizeof(str) == 7, потому что в действительности она будет установлена ​​в памяти, как это:

const char str[] = {'f', 'o', 'o', 'b', 'a', 'r', '\0'}; 

Это время компиляции постоянное и известно компилятором как только массив определен.

Если вы берете указатель на этот массив const char *strp = str, то sizeof(strp) == sizeof(char*).


Что касается размера int или T* (где T представляет собой любой тип объекта), то определяется реализацией. Но sizeof(T*) == sizeof(U*) == sizeof(void*), где T и U - любые типы объектов.

Единственная гарантия, которую вы получаете, - sizeof(char) == 1. Все остальное зависит от реализации.

С N4140 (C++ 14 проект стандарта)

§ 3.9.1 Основные типы
2 - Есть пять стандартных Подписанные целочисленных типов: «подписан символ», «короткие ИНТ», «Int», «long int» и «long long int». В этом списке каждый тип содержит как минимум столько же памяти, сколько и предшествующие ему в списке. Могут также существовать расширенные знаковые целые типы, определенные реализацией. Стандартные и расширенные подписанные целые типы называются целыми типами со знаком.Plain ints имеют натуральный размер, предложенный архитектурой среды исполнения ; другие подписанные целочисленные типы предоставляются для удовлетворения особых потребностей .

Так фактическая гарантия вы получаете:

sizeof(signed char) <= sizeof(int) <= sizeof(long) <= sizeof(long long) 

signed char имеет такой же размер, как char, но это особый тип и unsigned char имеет такой же размер, как и но другой особый тип снова.


На другой ноте, с большинством систем это будет выглядеть следующим образом:

64-разрядная операционная система, sizeof(T*) == 8
32-разрядная операционная система, sizeof(T*) == 4

и на 64 и 32-битные системы sizeof(int) обычно== 4.

, где T является любой объекта Type

+0

Я не думаю, что 'sizeof (T *) == sizeof (void *)' гарантирован. Весьма вероятно, что 'sizeof (T *) <= sizeof (void *)', потому что 'void *' должен иметь возможность удерживать указатель на _any_-объект, но особенно злой компилятор может добавить ненужные биты заполнения в 'T *'. Несколько меньше зла, «T *», указывающий на массив, может содержать размер кешированного массива. Это было бы полезно в режиме отладки. Но поскольку нет 'void []' a 'void *', возможно, не получится тот же подсчет. – MSalters

+0

@MSalters размер массива не будет частью самого указателя, а скорее выделен в виде нескольких байтов * до * указателя. Так или иначе, я бы это сделал, если бы я это сделал. Но nah, стандарт гарантирует, что размер указателя на объект всегда будет одного размера, а 'void *' является указателем на объект неизвестного типа. Вот почему литье 'void *' для работы с типами указателей является неопределенным поведением. – CoffeeandCode

 Смежные вопросы

  • Нет связанных вопросов^_^