Краткий ответ: потому что так определяется язык Си.
Более длинный ответ: строки C сами по себе ничего особенного. Это блок памяти, который содержит байты, как и любой другой блок. Но, определив соглашение о завершении строки на 0, все функции могут договориться о способах обработки строк.
Они могли бы быть выполнены таким образом, чтобы вы обрабатывали длину отдельно и всегда указывали указатель и длину для каждой функции. Это громоздко, поэтому лучше просто использовать терминатор. Это также медленнее в таких случаях, как конкатенация, поскольку сначала нужно искать конечное местоположение.
Что касается того, почему он не используется с другими типами, то иногда это так. И причина та же: она была согласована как соглашение и так же, как строки. Мы не знаем, сколько существует значений, поэтому в конце мы имеем дозорное значение. Это может быть ноль, 0 или другое значение. Но мы также не можем сделать это и предоставить количество элементов отдельно.
Также часто невозможно и / или не нужно использовать значение часового, например, если нам нужен полный тип данных или мы знаем размер данных. Например, если у нас есть изображение RGB, как мы определим конечное значение? Нам нужны все значения, которые байты могут определять цвета, чтобы у нас не было часового. Нам также не нужен, так как мы знаем размер изображения.
Что касается компьютера, он ничего не знает о данных. Он может обрабатывать только байты и слова и все, что он создан для обработки. Строки гораздо более высокого уровня и обрабатываются полностью в библиотеке используемого языка. Процессор просто перемещает данные в зависимости от того, что вы говорите. И, например, BIOS компьютера использует $ как символ-терминатор при печати строк, а не 0.