Указатель на 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 первый аргумент должен указывать на символ в массиве, который содержит строку (мы говорим "указывать на строку" для краткости); но поскольку второй аргумент может быть подсчитан по длине, он может указывать на символ в массиве, который не содержит строку.