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

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)
==>""
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值