Говнокод по пятницам. Эпизод 3. «Serial.println vs. Imperial Starfleet»

Больше всего меня удивляет то, что это уже было проделано, причем почти все присутствующие здесь, присутствовали и там, но никто про это не вспомнил! Так быстро забылось?

Т.е. ларчик открывается просто. Компилятор помечает все литералы таковыми, но не размещает их в памяти, оставляя это компоновщику (т.е. оставляя на момент, когда все файлы уже откомпилированы). Тот начинает размещать выбрасывая одинаковые и склеивая те, которые можно склеить в один без ущерба функциональности. Ну, а что Вы ему их плодить предлагаете? Таким образом, если где-то (в любом файле) был литерал “12345”, а где-то был “45”, он оставит только первый, в второму даст “адрес первого + 3”.

Поэтому после моего сообщения #12, я подумал, что интрига умерла, т.к. если сопоставить его с примером по ссылке выше, всё становится предельно понятным. println использует литерал "\r\n", компоновщик совместил его с наши литералом, который оканчивается так же, а мы его загадили :frowning:

Золотые слова. Согласен абсолютно. То, что Вы видите здесь – каприз художника, просто я так развлекаюсь.

На последок, примерчик “полезного” использования этого говнокода (реально “полезного”, но Боже меня упаси его кому-то советовать. Говнокод – он и есть говнокод. Так что, снова каприз художника).

Итак, создаём структуру, которая умеет печататься в поток (леденящую кровь историю про Имперский флот и звонок Дарта Вейдера сами допишите) и пишем

проверочный код
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;
	}

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

2 лайка