Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
size_t strlen(const char *str) {
const char *s;
for (s = str; *s; ++s);
return(s - str);
}
Давно придумали VLQ и его вариации. Первый бит обозначает наличие следующего байта, остальные биты — знаковые.
Получается для строк длиной до 127 (27) байт нужен 1 байт, для строк длиной до 16383 (214) — 2 байта и т.д.
Есть еще другой вариант — BER (и ASN.1), который используется, например, в SNMP: если установлен первый бит, то следующие 7 бит означают количество следующих байт содержащих значение, если же первый бит не установлен, то в следующих 7 битах само значение.
Кстати, в Delphi (камнями не кидаться), например, у типа String есть размер, но для совместимости в конце есть и null.
При использовании NUL-завершенной строки, попытка работы с ней частями, превышающими один байт, может привести к обращению к символам за символом NUL. Если NUL символ является последним байтом страницы виртуальной памяти и следующая страница не определена, это может привести к крушению процесса с ошибкой «страница не найдена» [«page not present»].>
void strcpy(char* _dest, const char* _src) {
int *dest = _dest, src = _src;
while (!contains_null_byte(*src)) {
*dest++ = *src++;
}
*dest = 0;
/* обработка граничных случаев */
}void strcpy(char* _dest, const char* _src) {
if (_dest & 3 != _src & 3) {
while (*_src) *_dest++ = *_src++;
*_dest = 0;
return;
}
while (_dest & 3 && *_dest) {
*_dest++ = *_src++;
}
int *dest = _dest, src = _src;
while (!contains_null_byte(*src)) {
*dest++ = *src++;
}
_dest = dest; _src = src;
while (*src) *_dest++ = *_src++;
*_dest = 0;
}
То есть, доступ к памяти всегда будет проходить по границе страницы, и будет определено, что строка либо заканчивается на текущей странице, либо продолжается на следующей.
Самая дорогая однобайтовая ошибка