Почему символ пробела не был выбран для 14-значных разделителей C++?
начиная с C++14, благодаря n3781 (что само по себе не дает ответа на этот вопрос), мы можем написать следующий код:
const int x = 1'234; // one thousand two hundred and thirty four
цель состоит в том, чтобы улучшить такой код:
const int y = 100000000;
и сделать его более читабельным.
подчеркивание (_
) символ уже был взят в C++11 пользовательскими литералами, а запятая (,
) имеет проблемы локализации-многие европейские страны сбивают с толку† использовать это как десятичный разделитель-и конфликты с оператором запятой, хотя мне интересно, какой реальный код мог быть нарушен, допустив, например,1,234,567
.
в любом случае, лучшим решением представляется пробелом:
const int z = 1 000 000;
эти смежные числовые литералы могут быть объединены препроцессором так же, как и строковые литералы:
const char x[5] = "a" "bc" "d";
вместо этого мы получаем Апостроф ('
), не используется ни одной системой письма, о которой я знаю как разделитель.
есть ли причина, что Апостроф был выбран вместо простого пространства?
† это сбивает с толку, потому что все эти языки в тексте поддерживают понятие запятой, "разрывающей" иначе атомарное предложение, с периодом, функционирующим для "завершения" предложения - для меня, по крайней мере, это совершенно аналогично запятой, "разрывающей" неотъемлемую часть числа и период "завершение" его готово для дробного ввода.
7 ответов:
есть предыдущая статья,n3499, которые говорят нам, что хотя сам Бьярне предложил пространства в качестве разделителей:
- он не соответствует синтаксису для ПП, и как минимум потребует расширения этого синтаксиса.
- что еще более важно, там будет какой-то синтаксический двусмысленность, когда шестнадцатеричная цифра в диапазоне [a-f] следует за пробелом. Препроцессор не будет знать, Следует ли выполнять подстановку символов, начиная с пробела.
- это, вероятно, сделает инструменты редактирования, которые захватывают "слова" менее надежными.
Я думаю, следующий пример является основной проблемой, отметил:
const int x = 0x123 a;
хотя на мой взгляд это обоснование довольно слабое. Я все еще не могу придумать реальный пример, чтобы сломать оно.
обоснование "инструментов редактирования" еще хуже, так как
1'234
ломает в основном каждый синтаксический маркер, известный человечеству (например, который используется Markdown в приведенном выше вопросе!) и делает обновленные версии указанных маркеров намного сложнее реализовать.тем не менее, к лучшему или худшему, это обоснование, которое привело к принятию апострофов вместо этого.
очевидная причина не использовать пробел в том, что новая строка также пробел, и что C++ обрабатывает все пробелы одинаково. И от стороны, я не знаю ни одного языка, который принимает произвольные пробелы как разделитель.
предположительно, Unicode 0xA0 (неразрывное пространство) может быть использован-это наиболее широко используется решение при наборе текста. Я вижу две проблемы с что, однако: во-первых, это не в базовом наборе символов, а во-вторых, это не визуально отличительные; вы не можете видеть, что это не космос просто смотрю на текст в обычном редакторе.
кроме того, есть не так много вариантов. Вы не можете использовать запятую, так как это уже легальный токен (и что-то вроде
1,234
в настоящее время юридический C++, со значением 234). И в контексте, где это может произойти в юридическом кодексе, напримерa[1,234]
. Хотя я не могу представить себе ничего реального код фактически использует это, есть основное правило, что нет юридической программы, независимо от того, насколько абсурдно, надо молча менять семантику.подобные соображения означают, что
_
не может быть использовано; если есть#define _234 * 2
, потомa[1_234]
молча изменил бы значение код.не могу сказать, что я особенно доволен выбором
'
, но это имеет преимущество используется в континентальной Европе, по крайней мере, в некоторые типы текстов. (Я, кажется, помню, что видел его на немецком языке, ибо пример, хотя в типичном запущенном тексте, немецкий, как и большинство других языки, будут использовать точку или неразрывное пространство. Но, может быть, так оно и было швейцарско-немецкий.) Проблема с'
анализа; последовательность'1'
is уже легально, как есть'123'
. Что-то вроде1'234
может быть1
, затем следует Начало константы персонажа; я не уверен, как далеко вы нужно смотреть вперед, чтобы принять решение. Нет никакой последовательности юридических C++, в котором за интегральной константой может следовать символ постоянный, так что нет никаких проблем с нарушение юридического кодекса, но это означает это лексическое сканирование внезапно становится очень зависимым от контекста.(касаемо вашего комментария: нет никакой логики в выборе десятичный или разделитель тысяч. Десятичный разделитель, например, является конечно, не полная остановка. Это просто произвольные соглашения.)
С wiki, у нас есть хороший пример:
auto floating_point_literal = 0.000'015'3;
здесь
.
оператор, а затем, если другой оператор будет встречен, мои глаза будут ждать чего-то видимого, как запятая или что-то еще, а не пробел.таким образом, Апостроф здесь гораздо лучше, чем пробелы.
с пробелами это было бы
auto floating_point_literal = 0.000 015 3;
который не чувствует себя так же хорошо, как в случае с апострофы.
в том же духе ответ Альберта Реншоу, Я думаю, что Апостроф более ясен, чем пространство, которое предлагает легкая гонка на орбите.
type a = 1'000'000'000'000'000'544'445'555; type a = 1 000 000 000 000 000 544 445 555;
пробел используется для многих вещей, таких как конкатенация строк, о которой упоминает OP, в отличие от апострофа, который в этом случае дает понять, что кто-то использует разделение цифр.
когда строк кода станет много, я думаю, что это улучшится читаемость, но я сомневаюсь, что это причина, по которой они выбирают его.
о пространствах, возможно, стоит взглянуть на этот C вопрос, который говорит:
язык не позволяет
int i = 10 000;
(целочисленный литерал-это один токен, промежуточный пробел разбивает его на два токена), но, как правило, нет никаких затрат, связанных с выражением инициализатора в виде выражения, которое является вычислением литералов:
int i = 10 * 1000; /* ten thousand */
Это правда, я не вижу никакого практического смысла:
if (a == 1 1 1 1 1) ...
Так что цифры могут быть объединены без двусмысленности но как насчет шестнадцатеричного числа?
0 x 1 a B 2 3
нет никакого способа избавиться от опечатки, делая это (обычно мы должны видеть ошибку)
Я бы предположил, что это потому, что при написании кода, если вы достигнете конца "линии" (ширина экрана) происходит автоматический разрыв строки (или "перенос слов"). Это приведет к тому, что ваш int будет разделен пополам, одна половина его будет на первой строке, вторая половина на второй... таким образом, все это остается вместе в случае
word-wrap
.
float floating_point_literal = 0.0000153; /* C, C++*/ auto floating_point_literal = 0.0000153; // C++11 auto floating_point_literal = 0.000'015'3; // C++14
комментировать не помешает:
/* 0. 0000 1530 */ float floating_point_literal = 0.00001530;
двоичные строки могут быть трудно разобрать:
long bytecode = 0b1111011010011001; /* gcc , clang */ long bytecode = 0b1111'0110'1001'1001; //C++14 // 0b 1111 0110 1001 1001 would be better, really. // It is how humans think.
макрос для рассмотрения:
#define B(W,X,Y,Z) (0b##W##X##Y##Z) #define HEX(W,X,Y,Z) (0x##W##X##Y##Z) #define OCT(O) (0##O) long z = B(1001, 1001, 1020, 1032 ); // result : long z = (0b1001100110201032); long h = OCT( 35); // result : long h = (035); // 35_oct => 29_dec long h = HEX( FF, A6, 3B, D0 ); // result : long h = (0xFFA6BD0);