Указатель на char, различные термины
Я использовал strncat
несколько раз, но сейчас проверю его формальное определение в стандарте:
#include <string.h>
char *strncat(char * restrict s1,
const char * restrict s2,
size_t n);
Функция strncat добавляет не более n символов (нулевой символ и последующие символы не добавляются) из массива, на который указывает s2, до конца строки, на которую указывает s1. Начальный символ s2 перезаписывает нулевой символ в конце s1. Конечный нулевой символ всегда добавляется к результату.
Обычно я думал бы о s1
и s2
просто как указатели на char. Но, как видно, стандарт называет их по-разному:
- строка, на которую указывает
s1
- массив, на который указывает
s2
Единственное различие между s1
и s2
является спецификатором const - это то, почему он называется массивом , а другой называется строкой?
Кроме того, в сноске:
Таким образом, максимальное количество символов, которое может быть в массиве, на которое указывает s1, равно strlen (s1) + n + 1.
Поэтому здесь они относятся к s1
по-другому: массив (а не строка), на который указывает s1
Есть ли какие-либо импликации этих разных способов вызова s1
и s2
?
Ответы
Ответ 1
Единственная разница между s1 и s2 - это определитель констант
Нет, не обязательно.
-
Целевой массив s1
должен быть уже завершенным нулем. Таким образом, его можно безопасно назвать строкой.
Цитата C11
, глава §7.1.1/p1, Определения терминов
Строка представляет собой непрерывную последовательность символов, заканчивающихся и включающих первый нуль персонаж. [...]
-
Однако для исходного массива s2
нулевое завершение не обязательно, если заданный размер n
меньше фактической длины массива. Поэтому он не должен быть строкой, всегда.
Итак, TL; DR. Целевой массив всегда будет строкой (следовательно, может использоваться взаимозаменяемо), но нет такой гарантии для исходного массива.
Также, чтобы подчеркнуть разницу в использовании, сравните это с описанием strcat()
, который имеет похожий синтаксис, минус размер. Таким образом, оба аргумента должны быть завершены в нуль, поскольку нет других средств для функции для определения конца исходного массива s2
. Таким образом, обратите внимание на формулировки там (выделение мое), из главы §7.24.3.1
Функция strcat
добавляет копию строки , на которую указывает s2
(включая завершающий нулевой символ) до конца строки , на которую указывает s1
. Начальный символ из s2
перезаписывает нулевой символ в конце s1
. Если копирование происходит между объекты, которые перекрываются, поведение undefined.
Здесь оба массива должны быть строками, и, следовательно, использование.
Ответ 2
В C строка NUL
-terminated, где массив не является (обязательно). Именно поэтому эта функция принимает параметр n
; потому что s2
не обязательно NUL
-terminated.
Ответ 3
Строка в C представляет собой массив символов, завершенных нулевым терминатором.
Массив символов - это массив символов, не обязательно завершающий нуль.
Причиной такого акцента здесь может быть то, что целевой массив должен быть строкой C - например, null завершено. Пока s2
не нужно. например См. Здесь
Начальный символ s2 перезаписывает нулевой символ в конце s1
Док говорит, что в конце s1
должен быть нулевой ограничитель.
Ответ 4
Массив - это область хранения. Строка представляет собой определенную последовательность символов (заканчивающуюся нулевым терминатором), которые могут быть сохранены в массиве.
Массив char
может содержать или не содержать строку в любое конкретное время.
(Я отправляю сообщения, несмотря на то, что уже есть несколько ответов, потому что другие ответы не делают четкие отношения контейнера).
С помощью функции strncat
первый аргумент должен указывать на символ в массиве, который содержит строку (мы говорим "указывать на строку" для краткости); но поскольку второй аргумент может быть подсчитан по длине, он может указывать на символ в массиве, который не содержит строку.