В чем разница между sv_catpv() и sv_catpvs()?

Согласно perlapi, sv_catpv() работает следующим образом:

Объединяет строку, оканчивающуюся NUL, с концом строки, находящейся в SV. Если SV имеет установленный статус UTF-8, то добавляемые байты должны быть действительными UTF-8. Обрабатывает магию «получить», но не магию «установить».

void sv_catpv(SV *const sv, const char* ptr)

Однако в большинстве руководств по XS, которые я нашел, используется sv_catpvs(), что делает следующее:

Аналогичен sv_catpvn, но вместо пары "строка/длина" принимает литеральную строку.

void sv_catpvs(SV* sv, const char* s)

Что ж, это не очень полезно, так что давайте посмотрим на sv_catpvn():

Объединяет строку с концом строки, находящейся в SV. len указывает количество байтов для копирования. Если SV имеет установленный статус UTF-8, то добавляемые байты должны быть действительными UTF-8. Обрабатывает магию «получить», но не магию «установить».

void sv_catpvn(SV *dsv, const char *sstr, STRLEN len)

Таким образом, sv_catpvn делает то же самое, что и sv_catpv, за исключением того, что принимает длину строки в качестве отдельного параметра, а sv_catpvs аналогичен sv_catpvn, за исключением того, что принимает литеральную строку.

Есть ли какая-то тонкая разница между sv_catpv и sv_catpvs, которую я упускаю, или это просто два способа сделать одно и то же?


person DarkMorford    schedule 29.10.2014    source источник


Ответы (1)


Согласно приведенным вами отрывкам, sv_catpvs принимает только строковый литерал.

const char *str = "foo";

sv_catpvs(sv, "foo");   // ok
sv_catpvs(sv, str);     // ERROR

sv_catpv, с другой стороны, принимает любое выражение, возвращающее строку.

sv_catpv(sv, "foo");    // ok
sv_catpv(sv, str);      // ok

Так почему же sv_catpvs вообще существует? Потому что это быстрее. Причина, по которой sv_catpvs принимает только строковый литерал, заключается в том, что это макрос, который расширяет

sv_catpvs(sv, "foo")

во что-то похожее на

sv_catpvn_flags(sv, "foo", sizeof("foo")-1, SV_GMAGIC)

который решает

sv_catpvn_flags(sv, "foo", 3, SV_GMAGIC)

во время компиляции. sv_catpv, с другой стороны, вынужден использовать более медленный strlen.

person ikegami    schedule 29.10.2014
comment
что означает, что sv_catpvs может включать нулевые символы. - person ysth; 29.10.2014