Ответ 1
Два типа R char
и character
на внутренней стороне C соответствуют CHARSXP
и STRSXP
соответственно. На уровне R каждый всегда имеет дело с объектами character
; одна строка, например:
y <- "My name is hasnain"
на самом деле является объектом character
длиной 1. Внутренне каждый элемент character
является char
, но R не предоставляет (AFAIK) прямой способ извлечения, создания и/или использования char
.
Хотя вы не можете создать объект char
/CHARSXP
с чистым R, просто получить его через интерфейс R/C с помощью функции mkChar
, которая берет стандартную строку C и превращает ее в CHARSXP
. Например, можно создать файл char.c
:
#include <stdio.h>
#include <stdlib.h>
#include <R.h>
#include <Rinternals.h>
SEXP returnCHAR() {
SEXP ret = PROTECT(mkChar("Hello World!"));
UNPROTECT(1);
return ret;
}
После компиляции через R CMD SHLIB char.c
со стороны R:
dyn.load("char.so") #linux dll; extension varies across platforms
x<-.Call("returnCHAR")
x
# <CHARSXP: "Hello World!">
typeof(x)
#[1] "char"
length(x)
#[1] 12
Кроме typeof
и length
я не нашел много других функций R, которые действуют на объекты char
. Даже as.character
не работает! Я не мог ни извлечь char
из стандартного вектора character
, ни вставить этот char
в существующий вектор character
(назначение не работает).
Функция c
приводит к list
, если объект является char
:
c(1,"a",x)
#[[1]]
#[1] 1
#
#[[2]]
#[1] "a"
#
#[[3]]
#<CHARSXP: "Hello World!">
Мы можем использовать .Internal(inspect())
(предупреждение: inspect
- это внутренняя неэкспонированная функция, и поэтому она может измениться в будущих выпусках. Не полагайтесь на нее), чтобы иметь представление о внутренней структуре объект. Насколько я знаю, объекты char
/CHARXSP
распределяются между строковыми векторами для экономии памяти. Например:
let<-letters[1:2]
.Internal(inspect(let))
#@1aff2a8 16 STRSXP g0c2 [NAM(1)] (len=2, tl=0)
# @1368c60 09 CHARSXP g0c1 [MARK,gp=0x61] [ASCII] [cached] "a"
# @16dc7c0 09 CHARSXP g0c1 [MARK,gp=0x60] [ASCII] [cached] "b"
mya<-"a"
.Internal(inspect(mya))
#@3068710 16 STRSXP g0c1 [NAM(3)] (len=1, tl=0)
# @1368c60 09 CHARSXP g0c1 [MARK,gp=0x61] [ASCII] [cached] "a"
Из приведенного выше вывода отметим две вещи:
STRSXP
объекты - это векторы объектовCHARSXP
, как мы уже упоминали;- строки хранятся в "глобальном пуле": строка
"a"
хранится по одному и тому же адресу, несмотря на то, что она создается независимо в двух разных объектах.