Как работает sizeof? Карта памяти для массива строк переменной длины - PullRequest
0 голосов
/ 03 ноября 2011
const char *pointerStr[]=
{
   "BEST123,      ",     // 0x00
   "Best2233,     ",     // 0x01
   "ABCDEFGH,     ",     // 0x02
   "123456,     ",     // 0x03
   "helloworld,     "     // 0x04
};
typedef struct
{
   char value;
   char name[40]; 
}StrInfo;

typedef struct
{
   int regMax;
   StrInfo info[60];   
} structNew;

void main()
{
  int i;
  structNew  pret;
for ( i=0;i<5;i++)
{     
  printf("PointerStr size of %dth %d \n",i,sizeof(pointerStr[i]));
  printf("pret size of %dth %d \n",i,sizeof(pret.info[i].name));
}
}

Приведенная выше программа выдаст результат

PointerStr size of 0th 4 
pret size of 0th 40 
PointerStr size of 1th 4 
pret size of 1th 40 
PointerStr size of 2th 4 
pret size of 2th 40 
PointerStr size of 3th 4 
pret size of 3th 40 
PointerStr size of 4th 4 
pret size of 4th 40 

Если я хочу узнать размер каждой строки в PointerStr, то как ее найти?Возможно ли использовать только strlen?у нас есть другой способ?Как этот массив переменной длины хранится в памяти?В результате получается, что pointerStr является переменной-указателем, а ее размер всегда равен 4. Пожалуйста, исправьте меня, если я ошибаюсь.

Ответы [ 4 ]

7 голосов
/ 03 ноября 2011

Длина строки C неявна: она определяется тем, где в строке находится завершающий символ '\0', поэтому для определения длины строки вам потребуется функция типа strlen.

Значения, возвращаемые sizeof, определяются компилятором путем просмотра типа данных вместо самих данных.

2 голосов
/ 03 ноября 2011

Причина, по которой вы получаете длину массива, но только размер указателя для char*, заключается в том, что sizeof не является вызовом функции, как кажется, но фактически вычисляется во время компиляции (за исключением массивов переменной длины.

Ваш код иллюстрирует ключевое различие между массивами и указателями.Во время компиляции компилятор точно знает, как долго ваш массив (40), потому что он имеет статический размер.С другой стороны, char* даже не обязательно указывает на строку с нулевым символом в конце, поэтому он возвращает размер указателя.

Правильный способ найти длину строк - использоватьstrlen.Однако обратите внимание, что это сообщит вам количество символов перед первым нулевым байтом (\0).Он не скажет вам, сколько памяти фактически выделено (что делает sizeof, когда возвращает 40).

1 голос
/ 03 ноября 2011

sizeof дает размер в байтах передаваемой ему переменной.Вы передаете массив указателей (указывающих на строки) на sizeof.Массивы в C «распадаются» на указатели, поэтому вы получаете указатель на первый элемент в вашем массиве указателей.

И тогда вы правильно получаете размер указателя в байтах (4 байта = 32 бита).адресная шина).

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

char array[10] = "...";
char* ptr = &array;

Решение состоит в том, чтобы либо хранить массивы другим способом, где вы можете использовать sizeof на самих массивах (как настоящий 2D-массив), либо хранитьвсе размеры массива в справочной таблице:

const size_t STRING_SIZES[] =
{
  sizeof("BEST123,      "),
  sizeof("Best2233,     "),
  sizeof("ABCDEFGH,     "),
  sizeof("123456,     "),
  sizeof("helloworld,     ")
};
1 голос
/ 03 ноября 2011

sizeof это вещь компилятора.Это дает размер данных, как видно во время компиляции.Это не имеет ничего общего с динамическим распределением памяти во время выполнения.Так что sizeof(char*) или sizeof(p) с переменной, объявленной как char* p;, часто имеют размер слова (то есть 4 на 32-битном процессоре, 8 на 64-битном процессоре) и не имеют ничего общего с динамическим распределением или сфактическая длина строки при запуске программы.

...