sizeof ("...") в Visual C ++ делает меня несчастным - PullRequest
7 голосов
/ 03 ноября 2011

Я писал фрагмент кода, где я использую sizeof("somestring") в качестве параметра функции, затем я заметил, что функция не возвращает ожидаемое значение, поэтому я пошел, чтобы увидеть соответствующий код asm, и обнаружил неприятный сюрприз,У кого-нибудь есть объяснение этому (см. Рисунок)?

Watch window shows sizeof==4, asm 5

Я знаю, что существует более 1000 различных способов сделать это, я уже реализовал еще один из них, но яхочу знать причину этого поведения.

Для любопытных это Visual Studio 2008 SP1.

Ответы [ 7 ]

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

Значение 5 является правильным. Константа включает нулевой байт терминатора. Отображение 4 в окне часов является неправильным.

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

Строковые литералы имеют тип "массив из n const char" ([lex.string], ¶8), где n - это число char s, из которых состоит строка. Поскольку строка заканчивается нулем, sizeof вернет количество «нормальных» символов плюс 1; окно просмотра неверно, это, вероятно, ошибка (как сказал @Gene Bushuyev, он, вероятно, интерпретирует его как указатель, а не как литерал = массив).

Тот факт, что значение 5 встроено в код, является нормальным, поскольку sizeof является оператором времени компиляции.

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

Помните, что строки C содержат конечный ноль \0. Пять - правильное значение.

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

есть символ конца строки C-String '\ 0' в конце каждой строки C-String, так что "pdfa" на самом деле является следующим массивом символов {'p', 'd', 'f', 'a', '\0'}, но \ 0 не будет напечатан.Вместо этого используйте strlen("pdfa").

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

Причина, по которой Things Go Wrong ™ здесь заключается в том, что вы выбрали слишком низкий уровень абстракции, memcmp.

На один уровень выше у вас есть strcmp и wcscmp.

И на один уровень выше, чем у вас есть std::string и std::wstring.

"Скорость" (ха!) Выбранной вами самой низкой возможной абстракции уровня смещена на

  • Неверный результат.

  • Неэффективность из-за недостатка знания типа (широкая или узкая строка, ваш код не знает).

  • Неэффективность из-за недостатка знаний о данных (в верхнем или нижнем регистре).

Вместо того, чтобы тратить время на решение проблем с неэффективным кодом нижнего уровня и тратить время на выяснение проблемдетали инструментов низкого уровня, используйте более высокий и безопасный уровень абстракции.


Только для записи, sizeof( "abcd" ) равно 5. Вероятно, как заметил Ганс Пассант, окно просмотра показывает размер указателя.Однако я не согласен с Гансом в том, что отладчик, как правило, не может узнать размер массива: для отладочной сборки он может знать что угодно и все об исходном источнике, включая дословный исходный источник, если это необходимо (и он отображает это дословнопервоисточник, в контексте).Таким образом, 4 является ИМХО ошибкой, так или иначе.Либо ошибка в коде отладчика, либо ошибка в его дизайне.

Cheers & hth.,

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

Ну, 5 - это правильное значение sizeof («PDFA»).4 символа + завершающий ноль.

Кроме того, имейте в виду, что «результат не обязательно соответствует размеру, вычисленному путем добавления требований к хранилищу отдельных членов. Параметр компилятора / Zp и прагма пакета влияютграницы выравнивания для членов. "

Говоря об окне Watch, я думаю, что оно просто показывает вам размер самого указателя (const char *).Попробуйте перекомпилировать программу в 64-битном режиме и проверьте, что будет отображаться в окне Watch.Если я прав, то увидишь 8.

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

Sizeof - это оператор, который оценивает size_t, обычно беззнаковое целое на 32-битных платформах.Вот почему вы видите это как 4 в отладчике.Оператор sizeof также является r-значением, поэтому вы не можете установить точку наблюдения в памяти.Если бы вы могли, местоположение будет содержать 5. Размер вашей строки плюс терминатор.

...