Я читал реализацию _countof
в MSVC и обнаружил деталь, которую не могу объяснить. Он реализован с помощью макроса __crt_countof
, который на C++ расширяется до (sizeof(*__countof_helper(_Array)) + 0)
(вот соответствующий код из заголовок). Почему там + 0
? Что было бы не так без него?
Почему реализация MSVC _count_of добавляет 0 к результату sizeof?
Ответы (1)
+ 0
добавлен, чтобы предотвратить потенциальное появление самого неприятного разбора! Без него такое выражение, как sizeof(*__countof_helper(_Array))
могло бы восприниматься как объявление функции при некоторых обстоятельствах.
EDIT: в настоящее время я пытаюсь создать пример контекста (согласно запросу в комментарии). А пока может оказаться полезным этот сильно упрощенный «эквивалент» (то, с чем я действительно сталкивался):
#include <iostream>
#include <vector>
int main() {
int num = 2;
// std::vector<char> vec(size_t(num)); // Won't compile - Most Vexing Parse
std::vector<char> vec(size_t(num) + 0); // Compiles - no longer a func decl!
vec[0] = 'a';
vec[1] = 'b';
std::cout << vec[0] << ' ' << vec[1] << std::endl;
return 0;
}
person
Adrian Mole
schedule
18.12.2019
Можете ли вы поделиться примером контекста, в котором это происходит?
- person François Andrieux; 18.12.2019
Дополнительные скобки вокруг
size_t(num)
также фиксируют это, что есть в макросе. Так что мне кажется, что макрос уже защищает от этого без +0
.
- person François Andrieux; 18.12.2019
@FrançoisAndrieux Но кодер M / S, который реализовал этот конкретный заголовок, возможно, не был уверен, поэтому добавил
+0
на всякий случай?
- person Adrian Mole; 18.12.2019
Определенно возможность. Намерение могло состоять в том, чтобы предотвратить mvp. В любом случае это не вредит, и логично, что никто не хочет брать на себя ответственность за его удаление и рисковать случайно взломать чей-то код, если окажется, что он делает что-то неожиданное.
- person François Andrieux; 18.12.2019
@FrançoisAndrieux Можно возможно «разбить» добавленные круглые скобки, попытавшись определить операцию приведения/преобразования с помощью:
#define BESILLY(arg) int _countof(arg)
- person Adrian Mole; 18.12.2019
sizeof
не size_t
. Это не тип. Я не понимаю, как это может вызвать MVP.
- person T.C.; 18.12.2019
@Т.С. Точно в точку. Мои попытки придумать пример пока не увенчались успехом! Я могу сделать это с
size_t
, но нет с sizeof
! Здесь я могу только предположить, что, возможно, было время (все еще может быть когда-нибудь?), когда sizeof
был реализован в функциональном стиле. И давайте не будем забывать, что лучше не исправлять чужой код, если вы не знаете, почему вы его «исправляете».
- person Adrian Mole; 19.12.2019
Можете ли вы привести какой-либо источник, что это является причиной этого? Парень, который на самом деле написал код, говорит другое.
- person M.M; 19.12.2019
@M.M Я могу только отослать вызывающего абонента к моему комментарию выше или, может быть, к этой альтернативе: /а>
- person Adrian Mole; 19.12.2019
__countof_helper
... - person Max Langhof   schedule 18.12.2019char
, что и в массиве аргументов. Таким образом,sizeof
этого массиваchar
должно быть таким же, как количество элементов в массиве аргументов. - person Kirill Dmitrenko   schedule 18.12.2019+0
. Не мог ли__countof_helper
просто вернуть_SizeOfArray
? - person François Andrieux   schedule 18.12.2019sizeof(a) / sizeof(a[0])
. Если вы случайно передадите указатель вместо статического массива в эту конструкцию, вы получите плохой результат. Связанная реализация не будет компилироваться для указателя. Вот аналогичный импл в Chromium и вот статья, содержащая полное объяснение, почему что-то подобное предпочтительнее и менее подвержено ошибкам (осмелюсь даже сказать, безошибочно). - person Kirill Dmitrenko   schedule 18.12.2019constexpr
. И код, который я связал, компилируется, но на самом деле не запускается. Теперь я понимаю, почему это делается именно так. Он сообщает размер через информацию о типе, которая поддерживает постоянное время компиляции. - person François Andrieux   schedule 18.12.2019