Чтение за концом строки - неопределенное поведение (UB).С UB нет никаких гарантий, что код будет вести себя так или иначе.Поведение может отличаться в разных системах, компиляторах, компоновщиках, флагах компиляции / компоновки, в зависимости от (казалось бы) несвязанного кода и версии всего вышеперечисленного.
Во многих системах переменные последовательно располагаются в стекев обратном порядке.Замените ваш printf на:
printf("a (%p) = %s\n", a, a);
printf("b (%p) = %s\n", b, b);
printf("c (%p) = %s\n", c, c);
Он печатает адреса массивов:
a (0x7fff559adad0) = 0123456789abcdef<F0>ښU<FF>
b (0x7fff559adac0) = 0123456789abcdef0123456789abcdef<F0>ښU<FF>
c (0x7fff559adaa0) = 0123456789abcdef<F0>ښU<FF>
Как видно из адресов, распечатка b
начинается с адреса 0x7fff559adac0, но продолжается хорошопо адресу a
(который начинается через 16 байтов после начала b
).
Также обратите внимание, что строки имеют ненужный конец.Дело в том, что в строке отсутствует терминатор '\ 0', а printf
продолжает читать следующий мусор (UB сам по себе).
Это происходит потому, что:
strncpy(a, "0123456789abcdef", sizeof(a));
устанавливает [], чтобы все его байты были равны "0123456789abcdef" без нулевого терминатора.Отсутствие '\ 0' printf не знает, где остановиться, и приведет к UB.
strncpy(b, "0123456789abcdef", sizeof(b));
также устанавливает b [], чтобы все его байты были равны "0123456789abcdef" без нулевого терминатора.Здесь также любой printf вызывает UB.Но на этот раз вместо случайного мусора он просто читает следующую строку.
Чтобы добавить оскорбление к травме, строка
strncpy(c, a, sizeof(c));
читает 32 байта из 16-байтового массива.Это тоже UB.В вашей (и моей) системе это читает a
и много мусора после него.Теоретически, это может привести к сбою вашей программы с нарушением доступа или ошибкой сегментации.
Некоторые вирусы и черви используют такие переполнения для чтения или записи данных, которые они не должны.