Jump to content

размер

sizeof унарный оператор в языках программирования C и C++ . Он генерирует размер хранилища выражения или типа данных , измеряемый в количестве единиц измерения размера char . Следовательно, конструкция sizeof (char) гарантированно равна 1 . Фактическое количество бит типа char указывается макросом препроцессора. CHAR_BIT , определенный в стандартном включаемом файле limit.h . На большинстве современных вычислительных платформ это восемь бит. Результат sizeof имеет беззнаковый целочисленный тип, который обычно обозначается size_t .

Оператор имеет единственный операнд, который является либо выражением, либо приведением типа данных, заключенного в круглые скобки. Типы данных могут быть не только примитивными типами , такими как целочисленные типы и типы с плавающей запятой , но также типами указателей и составными типами данных ( объединениями , структурами и классами C++ ).

Многие программы должны знать размер хранилища определенного типа данных. Хотя для любой конкретной реализации C или C++ размер определенного типа данных является постоянным, размеры даже примитивных типов в C и C++ могут определяться по-разному для разных платформ реализации. Например, при выделении пространства массива во время выполнения можно использовать следующий код, в котором оператор sizeof применяется к приведению типа int :

int *pointer =  malloc(10 * sizeof (int));

В этом примере функция malloc выделяет память и возвращает указатель на блок памяти. Размер выделенного блока равен количеству байтов для одного объекта типа int , умноженному на 10, что обеспечивает место для десяти целых чисел.

Обычно небезопасно предполагать размер любого типа данных. Например, хотя большинство реализаций C и C++ в 32-битных системах определяют тип int как четыре октета, этот размер может измениться при переносе кода в другую систему, что приведет к нарушению кода. Исключением является тип данных char , который всегда имеет размер 1 в любой реализации C, соответствующей стандартам. Кроме того, часто бывает трудно предсказать размеры составных типов данных, таких как struct или Union , из-за заполнения. Использование sizeof повышает читабельность, поскольку позволяет избежать безымянных числовых констант ( магических чисел ).

Эквивалентный синтаксис для выделения того же пространства массива получается в результате использования разыменованной формы указателя на адрес хранилища, на этот раз применяя оператор к переменной-указателю:

int *pointer =  malloc(10 * sizeof *pointer);

Использовать

[ редактировать ]

Оператор sizeof создает необходимое пространство памяти для своего операнда при компиляции кода. Операнд записывается после ключевого слова sizeof и может быть символом пространства хранения, например, переменной, выражением или именем типа. Круглые скобки для операнда необязательны, за исключением случаев указания имени типа. Результатом операции является размер операнда в байтах или размер требуемой памяти. Для выражений он оценивает размер представления для типа, который возникнет в результате вычисления выражения, которое не выполняется.

Например, поскольку sizeof (char) определен как 1 [1] и предполагая, что целочисленный тип имеет длину четыре байта, печатается следующий фрагмент кода 1,4 :

char c;
printf ("%zu,%zu\n", sizeof c, sizeof (int));

Некоторые стандартные файлы заголовков, такие как stddef.h , определяют size_t для обозначения целочисленного типа без знака результата выражения sizeof . Спецификатор printf ширины z предназначен для форматирования этого типа.

sizeof нельзя использовать в выражениях препроцессора C , таких как #if , потому что это элемент языка программирования, а не синтаксиса препроцессора, который не имеет типов данных.

В следующем примере на C++ оператор sizeof используется с шаблонами с переменным числом аргументов.

template <typename... Args>
std::size_t GetSize (Args&&... args)
{
    /* Get size of parameter pack.*/
    std::size_t Count = sizeof... (Args);
    return Count;           
}

sizeof можно использовать с шаблонами с переменным числом аргументов в C++11 и более поздних версиях в пакете параметров для определения количества аргументов.

Приложение к массивам

[ редактировать ]

Когда sizeof применяется к имени массива, результатом является количество байтов, необходимое для хранения всего массива. Это одно из немногих исключений из правила, согласно которому имя массива преобразуется в указатель на первый элемент массива, и возможно только потому, что фактический размер массива фиксирован и известен во время компиляции, когда sizeof оператор оценивается. Следующая программа использует sizeof для определения размера объявленного массива, избегая переполнения буфера при копировании символов:

#include <stdio.h>

int main(int argc, char **argv)
{
  char buffer[10]; /* Array of 10 chars */

  /* Copy at most 9 characters from argv[1] into buffer,
   * null-terminate the buffer. */
  snprintf(buffer, sizeof buffer, "%s", argv[1]);

  return 0;
}

Здесь, sizeof буфер эквивалентен 10 * sizeof buffer [0] , что равно 10, поскольку размер типа char определен как 1.

C99 добавляет в структуры поддержку гибких членов массива. Эта форма объявления массива разрешена только в качестве последнего элемента в структурах и отличается от обычных массивов тем, что компилятору не указывается длина. Для структуры с именем s, содержащей гибкий элемент массива с именем a , sizeof s поэтому эквивалентен offsetof (s, a) :

#include <stdio.h>

struct flexarray {
    char val;
    int array[];  /* Flexible array member; must be last element of struct */
};

int main(int argc, char **argv)
{
    printf("sizeof (struct flexarray) == %zu\n", sizeof (struct flexarray));
    return 0;
}

В этом случае оператор sizeof возвращает размер структуры, включая любые дополнения, но без какого-либо места для хранения, разрешенного для массива. Большинство платформ выдают следующий результат:

sizeof (struct flexarray) == 4

C99 также позволяет использовать массивы переменной длины, длина которых указана во время выполнения. [2] хотя эта функция считается необязательной реализацией в более поздних версиях стандарта C. В таких случаях оператор sizeof частично оценивается во время выполнения, чтобы определить объем памяти, занимаемый массивом.

#include <stddef.h>

size_t flexsize(int n)
{
   char b[n + 3];   /* Variable length array */
   return sizeof b;  /* Execution time sizeof */
}

int main(void)
{
  size_t size = flexsize(10); /* flexsize returns 13 */
  return 0;
}

sizeof можно использовать для определения количества элементов в массиве путем деления размера всего массива на размер одного элемента. Это следует использовать с осторожностью; При передаче массива в другую функцию он «распадется» до типа указателя. На этом этапе sizeof вернет размер указателя, а не общий размер массива. В качестве примера с правильным массивом:

int main (void)
{
   int tab [10];
   printf ("Number of elements in the array: %zu\n", sizeof tab / sizeof tab [0]); /* yields 10 */
   return 0;
}

Неполные типы

[ редактировать ]

sizeof может применяться только к «полностью» определенным типам. В случае с массивами это означает, что размеры массива должны присутствовать в его объявлении и что тип элементов должен быть полностью определен. Для struct и Union это означает, что должен существовать список членов полностью определенных типов. Например, рассмотрим следующие два исходных файла:

/* file1.c */
int arr [10];
struct x {int one; int two;};
/* more code */

/* file2.c */
extern int arr [];
struct x;
/* more code */

Оба файла совершенно легальны на языке C, и код на них file1.c может применять sizeof к arr и структура х . Однако это незаконно для кода в file2.c для этого, поскольку определения в file2.c не завершены. В случае arr код не указывает размерность массива; без этой информации компилятор не сможет узнать, сколько элементов находится в массиве, и не сможет вычислить общий размер массива. Аналогично, компилятор не может вычислить размер struct x, поскольку она не знает, из каких элементов она состоит, и поэтому не может вычислить сумму размеров членов структуры (и заполнения). Если программист указал размер массива в своем объявлении в file2.c или завершил определение struct x, предоставив список членов, это позволит применить sizeof к arr или struct x в этом исходном файле.

Члены объекта

[ редактировать ]

В C++11 появилась возможность применять параметр sizeof к конкретным членам класса без необходимости создавать для этого экземпляр объекта. [3] Следующий пример, например, дает 4 и 8 на большинстве платформ.

#include <iostream>

struct foo {
  int a;
  int b;
};

int main ()
{
  std::cout << sizeof foo::a << "\n" << sizeof (foo) << "\n";
}

Пакеты шаблонов Variadic

[ редактировать ]

В C++11 представлены шаблоны с переменным числом вариантов ; ключевое слово sizeof, за которым следует многоточие, возвращает количество элементов в пакете параметров.

template <typename... Args>
void print_size (Args... args)
{
  std::cout << sizeof... (args) << "\n";
}

int main ()
{
  print_size (); // outputs 0
  print_size ("Is the answer", 42, true); // outputs 3
}

Выполнение

[ редактировать ]

При применении к типу данных или переменной фиксированной длины выражения с оператором sizeof оцениваются во время компиляции программы; они заменяются постоянными значениями результата. Стандарт C99 представил массивы переменной длины (VLA), которые требовали оценки таких выражений во время выполнения программы. Во многих случаях особенности реализации могут быть задокументированы в документе двоичного интерфейса приложения (ABI) для платформы, определяющем форматы, заполнение и выравнивание для типов данных, которым должен соответствовать компилятор.

Заполнение структуры

[ редактировать ]

При вычислении размера любого типа объекта компилятор должен учитывать любое необходимое выравнивание структуры данных для обеспечения эффективности или архитектурных ограничений. Многие компьютерные архитектуры не поддерживают многобайтовый доступ, начиная с любого байтового адреса, не кратного размеру слова, и даже если архитектура это позволяет, обычно процессор может получить объект, выровненный по слову, быстрее, чем он может получить объект. который охватывает несколько слов в памяти. [4] Поэтому компиляторы обычно выравнивают структуры данных по крайней мере по границе слова , а также выравнивают отдельные члены по соответствующим границам. В следующем примере структура «студент», скорее всего, будет выровнена по границе слова, где также начинается оценка участника, участника, а возраст скорее всего, начнется с адреса следующего слова. Компилятор выполняет последнее, вставляя байты заполнения между элементами по мере необходимости для удовлетворения требований выравнивания. В конце структуры также может быть дополнение для обеспечения правильного выравнивания в случае, если структура используется как элемент массива.

Таким образом, совокупный размер структуры в C может быть больше суммы размеров ее отдельных членов. Например, во многих системах печатается следующий код: 8 :

struct student {
  char grade; /* char is 1 byte long */
  int age; /* int is 4 bytes long */
};

printf ("%zu", sizeof (struct student));

См. также

[ редактировать ]
  1. ^ «Стандарт C99 (ISO/IEC9899)» (PDF) . ИСО/МЭК . 7 сентября 2007 г. 6.5.3.4.3, с. 80 . Проверено 31 октября 2010 г.
  2. ^ «Проект ISO/IEC 9899 комитета WG14/N1124» (PDF) . 6 мая 2005 г. 6 мая 2005 г. 6.5.3.4 Оператор sizeof .
  3. ^ «N2253 Расширение sizeof для применения к нестатическим элементам данных без объекта (версия 1)» .
  4. ^ Ренцш, Джонатан (8 февраля 2005 г.). «Выравнивание данных: выпрямляйтесь и летите вправо» . ИБМ . Проверено 29 сентября 2014 г.
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 75d98ff886cfb2a275fc7c255ef07db7__1712998500
URL1:https://arc.ask3.ru/arc/aa/75/b7/75d98ff886cfb2a275fc7c255ef07db7.html
Заголовок, (Title) документа по адресу, URL1:
sizeof - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)