欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于s[s.length,1]为什么返回""

程序员文章站 2022-07-13 23:36:28
...
ROR群(15917997)里有朋友问到一个问题
s="hello"
s[s.length,1]为什么返回"",而不是返回nil或其他

群里展开了讨论,我翻了翻ruby源代码,试着做出解释:
首先查了API,
string[integer, integer]会执行
rb_str_substr(str, NUM2LONG(argv[0]), NUM2LONG(argv[1]));



rb_str_substr是这样的:
VALUE
rb_str_substr(str, beg, len)
VALUE str;
long beg, len;
{
VALUE str2;

if (len < 0) return Qnil;
if (beg > RSTRING(str)->len) return Qnil;
if (beg < 0) {
beg += RSTRING(str)->len;
if (beg < 0) return Qnil;
}
if (beg + len > RSTRING(str)->len) {
len = RSTRING(str)->len - beg;
}
if (len < 0) {
len = 0;
}
if (len == 0) {
str2 = rb_str_new5(str,0,0);
}
else if (len > sizeof(struct RString)/2 &&
beg + len == RSTRING(str)->len && !FL_TEST(str, STR_ASSOC)) {
str2 = rb_str_new4(str);
str2 = str_new3(rb_obj_class(str2), str2);
RSTRING(str2)->ptr += RSTRING(str2)->len - len;
RSTRING(str2)->len = len;
}
else {
str2 = rb_str_new5(str, RSTRING(str)->ptr+beg, len);
}
OBJ_INFECT(str2, str);

return str2;
}


看到这两句
if (len < 0) return Qnil;
if (beg > RSTRING(str)->len) return Qnil;

意思是说要截取的字串长度如果为负数,返回nil
开始的位置超出了原字串的长度,也返回nil

往下看,因为s.lenght刚好等于RSTRING(str)->len,其实会执行到
str2 = rb_str_new5(str, RSTRING(str)->ptr+beg, len);


rb_str_new5是这样的
VALUE
rb_str_new5(obj, ptr, len)
VALUE obj;
const char *ptr;
long len;
{
return str_new(rb_obj_class(obj), ptr, len);
}


主要是调用了str_new

static VALUE
str_new(klass, ptr, len)
VALUE klass;
const char *ptr;
long len;
{
VALUE str;

if (len < 0) {
rb_raise(rb_eArgError, "negative string size (or size too big)");
}

str = str_alloc(klass);
RSTRING(str)->len = len;
RSTRING(str)->aux.capa = len;
RSTRING(str)->ptr = ALLOC_N(char,len+1);
if (ptr) {
memcpy(RSTRING(str)->ptr, ptr, len);
}
RSTRING(str)->ptr[len] = '\0';
return str;
}



到了
  if (ptr) {
memcpy(RSTRING(str)->ptr, ptr, len);
}



ptr其实已经指向了"hello"的最后一个字符,也就是'\0'了,执行完memcpy后,str成了"",再最后执行
RSTRING(str)->ptr[len] = '\0';

这一句加""加上'\0',是c语言的空字符串.

最后的结果就是""了.

路线是这样的
s[s.length,1]
==> rb_str_substr("hello", 5, 1);
==> rb_str_new5("hello",ptr=5,1);
==> str_new("hello",ptr=5,1)
==>memcpy("hello",ptr=5,1)
==>""
相关标签: C C++ C# Ruby