Больше всего меня удивляет то, что это уже было проделано, причем почти все присутствующие здесь, присутствовали и там, но никто про это не вспомнил! Так быстро забылось?
Т.е. ларчик открывается просто. Компилятор помечает все литералы таковыми, но не размещает их в памяти, оставляя это компоновщику (т.е. оставляя на момент, когда все файлы уже откомпилированы). Тот начинает размещать выбрасывая одинаковые и склеивая те, которые можно склеить в один без ущерба функциональности. Ну, а что Вы ему их плодить предлагаете? Таким образом, если где-то (в любом файле) был литерал “12345”, а где-то был “45”, он оставит только первый, в второму даст “адрес первого + 3”.
Поэтому после моего сообщения #12, я подумал, что интрига умерла, т.к. если сопоставить его с примером по ссылке выше, всё становится предельно понятным. println
использует литерал "\r\n"
, компоновщик совместил его с наши литералом, который оканчивается так же, а мы его загадили
Золотые слова. Согласен абсолютно. То, что Вы видите здесь – каприз художника, просто я так развлекаюсь.
На последок, примерчик “полезного” использования этого говнокода (реально “полезного”, но Боже меня упаси его кому-то советовать. Говнокод – он и есть говнокод. Так что, снова каприз художника).
Итак, создаём структуру, которая умеет печататься в поток (леденящую кровь историю про Имперский флот и звонок Дарта Вейдера сами допишите) и пишем
проверочный код
struct SomeStruct : public Printable {
int a, b, c, d, e, f, g, h;
SomeStruct(const int _a, const int _b, const int _c, const int _d) : a(_a), b(_b), c(_c), d(_d) {
e = a + b;
f = c + d;
g = e + f;
h = g - f;
}
size_t printTo(Print& p) const {
size_t res = p.print('{');
res += p.print(a);
res += p.print("; ");
res += p.print(b);
res += p.print("; ");
res += p.print(c);
res += p.print("; ");
res += p.print(d);
res += p.print("; ");
res += p.print(e);
res += p.print("; ");
res += p.print(f);
res += p.print("; ");
res += p.print(g);
res += p.print("; ");
res += p.print(h);
res += p.print('}');
return res;
}
};
void setup(void) {
Serial.begin(9600);
SomeStruct ss(1,2,3,4);
Serial.println(ss);
}
void loop(void) {}
Запускаем и получаем ожидаемый результат.
{1; 2; 3; 4; 3; 7; 10; 3}
А теперь заменим функцию печати на
вот такую (с нашим говнокодом)
size_t printTo(Print& p) const {
constexpr static char * const brbn = (char *) "\r\n";
size_t res = p.print('{');
* brbn = ';';
* (brbn+1) = ' ';
res += p.println(a);
res += p.println(b);
res += p.println(c);
res += p.println(d);
res += p.println(e);
res += p.println(f);
res += p.println(g);
* brbn = '\r';
* (brbn+1) = '\n';
res += p.print(h);
res += p.print('}');
return res;
}
запустим и убедимся, что результат не изменился, зато функция печати серьёзно сократилась и сократилась бы тем больше, чем больше разных переменных в ней печатается.