关于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是这样的:
看到这两句
意思是说要截取的字串长度如果为负数,返回nil
开始的位置超出了原字串的长度,也返回nil
往下看,因为s.lenght刚好等于RSTRING(str)->len,其实会执行到
rb_str_new5是这样的
主要是调用了str_new
到了
ptr其实已经指向了"hello"的最后一个字符,也就是'\0'了,执行完memcpy后,str成了"",再最后执行
这一句加""加上'\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)
==>""
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)
==>""
推荐阅读
-
关于s[s.length,1]为什么返回""
-
关于如何使`(a === 1 && a === 2 && a === 3)`返回`true`问题的思考
-
关于创建keil工程后选择芯片时为什么没有STM32F1xx系列的芯片?
-
php 为什么执行 shell 返回值为 1?
-
为什么在python3里b=a=1是合理表达式,而print(a=1)却不是。a=1为什么没有返回值?
-
关于上面这个递归,为什么最后的$a值为0?不是1吗
-
关于上面这个递归,为什么最后的$a值为0?不是1吗
-
php 为什么我ajax返回值为1 为什么前台接收alert(data)显示的确实整个网页页面的html代码
-
为什么在python3里b=a=1是合理表达式,而print(a=1)却不是。a=1为什么没有返回值?
-
php 为什么执行 shell 返回值为 1?