
指针的进阶
指针的主题,我们在初级阶段的《指针》章节已经接触过了,我们知道了指针的概念:
- 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。
- 指针的大小是固定的4/8个字节(32位平台/64位平台)。
- 指针是有类型,指针的类型决定了指针的±整数的步长,指针解引用操作的时候的权限。
- 指针的运算。
这个章节,我们继续探讨指针的高级主题。
在指针的类型中我们知道有一种指针类型为字符指针 char* ;
一般使用:
#include <stdio.h>
int main()
{
char ch = 'w';
char* pc = &ch;
*pc = 'w';
return 0;
}
还有一种使用方式如下:
#include <stdio.h>
int main()
{
const char* pstr = "hello bit.";//这里是把一个字符串放到pstr指针变量里了吗?
printf("%s\n", pstr);
return 0;
}
代码 const char* pstr = “hello bit.”;
特别容易让同学以为是把字符串 hello bit 放到字符指针 pstr 里了,但是本质是把字符串 hello bit. 首字符的地址放到了pstr中。

上面代码的意思是把一个常量字符串的首字符 h 的地址存放到指针变量 pstr 中。
那就有可这样的面试题:
#include <stdio.h>
int main()
{
char str1[] = "hello bit.";
char str2[] = "hello bit.";
const char* str3 = "hello bit.";
const char* str4 = "hello bit.";
if (str1 == str2)
printf("str1 and str2 are same\n");
else
printf("str1 and str2 are not same\n");
if (str3 == str4)
printf("str3 and str4 are same\n");
else
printf("str3 and str4 are not same\n");
return 0;
}
这里最终输出的是:

这里str3和str4指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域,当几个指针。指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同,str3和str4不同。
在《指针》章节 我们也学了指针数组,指针数组是一个存放指针的数组。
这里我们再复习一下,下面指针数组是什么意思?
类比一下:
int main()
{
char* arr[] = { "abcdef", "hehe", "qwer" };
int i = 0;
for (i = 0; i < 3; i++)
{
printf("%s\n", arr[i]);
}
return 0;
}


再举一个例子:
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 2,3,4,5,6 };
int arr3[] = { 3,4,5,6,7 };
//arr[i] == *(arr+i)
//arr是一个存放整型指针的数组
int* arr[] = { arr1, arr2, arr3 };
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 5; j++)
{
//printf("%d ", arr[i][j]);
printf("%d ", *(arr[i]+j));
}
printf("\n");
}
return 0;
}

数组指针是指针?还是数组?
答案是:指针。
我们已经熟悉:
整形指针: int * pint; 能够指向整形数据的指针。
浮点型指针: float * pf; 能够指向浮点型数据的指针。
那数组指针应该是:能够指向数组的指针。
类比:
int *p1[10];
int (*p2)[10];
//p1, p2分别是什么?
解释:
int (p)[10];
//解释:p先和结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫数组指针。
//这里要注意:[ ]的优先级要高于号的,所以必须加上( )来保证p先和结合。
总结:
指针数组 - 是数组 - 是一种存放指针的数组。
数组指针 - 是指针 - 是一种指向数组的指针 - 存放的是数组的地址。
//指针数组 - 是数组 - 是一种存放指针的数组
//数组指针 - 是指针 - 是一种指向数组的指针 - 存放的是数组的地址
int main()
{
//指针数组
char* arr[4];
//数组指针
int arr[5];
int (*p)[5] = &arr;
return 0;
}
对于下面的数组:
int arr[10];
arr 和 &arr 分别是啥?
我们知道arr是数组名,数组名表示数组首元素的地址。
那&arr数组名到底是啥?
我们看一段代码:
int main()
{
int arr[10] = { 0 };
printf("%p\n", arr);
printf("%p\n", &arr[0]);
printf("%p\n", &arr);
return 0;
}
运行结果如下:

可见数组名和&数组名打印的地址是一样的。
难道两个是一样的吗?
我们再看一段代码:
//数组名绝大部分情况下是数组首元素的地址
//但是有2个例外:
//1. sizeof(数组名) - sizeof内部单独放一个数组名的时候,数组名表示的整个数组,计算得到的是数组的总大小
//2. &arr - 这里的数组名表示整个数组,取出的是整个数组的地址,从地址值的角度来讲和数组首元素的地址是一样的,但是意义不一样
//
int main()
{
int arr[10] = { 0 };
//printf("%d\n", sizeof(arr));
printf("%p\n", arr);//int *
printf("%p\n", arr+1);//4
printf("%p\n", &arr[0]);//int*
printf("%p\n", &arr[0]+1);//4
printf("%p\n", &arr);//int(*)[10]
printf("%p\n", &arr+1);//40
int (*p)[10] = &arr;//p是一个数组指针
//int(*)[10]
return 0;
}

根据上面的代码我们发现,其实&arr和arr,虽然值是一样的,但是意义应该不一样的。
实际上: &arr 表示的是数组的地址,而不是数组首元素的地址。(细细体会一下)
本例中 &arr 的类型是: int(*)[10] ,是一种数组指针类型
数组的地址+1,跳过整个数组的大小,所以 &arr+1 相对于 &arr 的差值是40。
注意:
数组名绝大部分情况下是数组首元素的地址
但是有2个例外:
- sizeof(数组名) - sizeof内部单独放一个数组名的时候,数组名表示的整个数组,计算得到的是数组的总大小
- &arr - 这里的数组名表示整个数组,取出的是整个数组的地址,从地址值的角度
讲和数组首元素的地址是一样的,但是意义不一样
那数组指针是怎么使用的呢?
既然数组指针指向的是数组,那数组指针中存放的应该是数组的地址。
看代码:
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
int (* p)[10] = &arr;
int i = 0;
//p --- &arr
//*p --- *&arr
//*p --- arr
//虽然对,但是不推荐
for (i = 0; i < sz; i++)
{
printf("%d ", (*p)[i]);
}
//虽然对,但是不推荐
for (i = 0; i < sz; i++)
{
printf("%d ", *((*p) + i));
}
//使用指针来访问
int* p = arr;
for (i = 0; i < sz; i++)
{
printf("%d ", *(p + i));
}
//下标的形式访问数组
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
一个数组指针的使用:
#include <stdio.h>
void print(int arr[3][5], int r, int c)
{
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 5; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main()
{
int arr[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
//二维数组的数组名,也表示首元素的地址
//二维数组的首元素是第一行
//首元素的地址就是第一行的地址,是一个一维数组的地址
//
print(arr, 3, 5);
return 0;
}
用数组指针来做:
#include <stdio.h>
void print(int(*arr)[5], int r, int c)
{
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 5; j++)
{
//printf("%d ", *(*(arr + i) + j));//arr[i]
printf("%d ", arr[i][j]);//arr[i]
}
printf("\n");
}
}
int main()
{
int arr[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
//二维数组的数组名,也表示首元素的地址
//二维数组的首元素是第一行
//首元素的地址就是第一行的地址,是一个一维数组的地址
//
print(arr, 3, 5);
return 0;
}
图片讲解:

学了指针数组和数组指针我们来一起回顾并看看下面代码的意思:
1. int arr[5];
2. int *parr1[10];
3. int (*parr2)[10];
4. int (*parr3[10])[5];
第一个是数组
第二个是指针数组
第三个是数组指针
第四个原理:parr3是数组,数组中存放的指针,该指针指向的又是数组,所以是指针数组里面存放的数组指针
第四个图片讲解:

在写代码的时候难免要把【数组】或者【指针】传给函数,那函数的参数该如何设计呢?
#include <stdio.h>
void test(int arr[])//ok?
{}
void test(int arr[10])//ok?
{}
void test(int* arr)//ok?
{}
void test2(int* arr[20])//ok?
{}
void test2(int** arr)//ok?
{}
int main()
{
int arr[10] = { 0 };
int* arr2[20] = { 0 };
test(arr);
test2(arr2);
}
}
结果是都可以运行。
结论:
一维数组传参,传参可以是数组,也可以是指针的,当形参是指针的时候,要注意类型。
void test(int arr[3][5])//ok?可以
{}
void test(int arr[][])//ok?不可以
{}
void test(int arr[][5])//ok?可以
{}
//总结:二维数组传参,函数形参的设计只能省略第一个[]的数字。
//因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。
//这样才方便运算。
void test(int* arr)//ok?不可以
{}
void test(int* arr[5])//ok?不可以
{}
void test(int(*arr)[5])//ok?可以
{}
void test(int** arr)//ok?不可以
{}
int main()
{
int arr[3][5] = { 0 };
test(arr);
}
结论:
二维数组传参
传参可以是指针,也可以是数组
如果是数组,行可以省略,但是列不能省略
如果是指针,传过去的是第一行的地址,形参就应该是数组指针
#include <stdio.h>
void print(int* p, int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d\n", *(p + i));
}
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9 };
int* p = arr;
int sz = sizeof(arr) / sizeof(arr[0]);
//一级指针p,传给函数
print(p, sz);
return 0;
}
思考:
当一个函数的参数部分为一级指针的时候,函数能接收什么参数?

#include <stdio.h>
void test(int** ptr)
{
printf("num = %d\n", **ptr);
}
int main()
{
int n = 10;
int* p = &n;
int** pp = &p;
test(pp);
test(&p);
return 0;
}
思考:
当函数的参数为二级指针的时候,可以接收什么参数?

类比方法:
整型指针 - 指向整型的指针 int*
字符指针 - 指向字符的指针 char*
数组指针 - 指向数组的指针 int arr[ 10 ]* ; int( p )[ 10 ] = & arr ;
函数指针 - 指向函数的指针 int
数组指针中存放的是数组的地址
函数指针中存放的应该是函数的地址
函数有地址吗?
首先看一段代码:
#include <stdio.h>
void test()
{
printf("hehe\n");
}
int main()
{
printf("%p\n", test);
printf("%p\n", &test);
return 0;
}
输出的结果:

输出的是两个地址,这两个地址是 test 函数的地址。
数组:
数组名
&数组名
函数名和&函数名 都是函数的地址,没有区别。
那我们的函数的地址要想保存起来,怎么保存?
下面我们看代码:
void test()
{
printf("hehe\n");
}
//下面pfun1和pfun2哪个有能力存放test函数的地址?
void (*pfun1)();
void* pfun2();
首先,能给存储地址,就要求pfun1或者pfun2是指针,那哪个是指针?
答案是:
pfun1可以存放。pfun1先和*结合,说明pfun1是指针,指针指向的是一个函数,指向的函数无参数,返回值类型为void。
举一个例子:
int Add(int x, int y)
{
return x + y;
}
//&函数名得到就是函数的地址
int main()
{
//printf("%p\n", &Add);
//printf("%p\n", Add);
//pf就是函数指针
int (* pf)(int, int) = Add;//函数的地址要存起来,就得放在【函数指针变量】中
int ret = (*pf)(3, 5);
//int ret = Add(3, 5);
//int ret = pf(3, 5);
printf("%d\n", ret);
return 0;
}
在练习一个函数指针的例子
char* test(int c, float* pf)
{
}
int main()
{
char* (*pt)(int, float*) = test;
return 0;
}
阅读两段有趣的代码:
//代码1
(*(void (*)())0)();
//代码2
void (*signal(int , void(*)(int)))(int);
//代码1
int main()
{
//1. 将0强制类型转换为void (*)() 类型的函数指针
//2. 这就意味着0地址处放着一个函数,函数没参数,返回类型是void
//3. 调用0地址处的这个函数
//下面代码是一次函数调用
(*( void (*)() ) 0)();
return 0;
}
- 将0强制类型转换为void (*)() 类型的函数指针
- 这就意味着0地址处放着一个函数,函数没参数,返回类型是void
- 调用0地址处的这个函数
typedef void(*pf_t)(int);//将void(*)(int)类型重新起个别名叫pf_t
//
typedef void(*pf_t2)(int);//pf_t2是类型名
void(*pf)(int);//pf是函数指针变量的名字
//代码2
int main()
{
void (* signal(int, void(*)(int) ) )(int);
//
pf_t signal(int, pf_t);
//上述的代码是一个函数的声明
//函数的名字是signal
//signal函数的参数第一个是int类型,第二个是void(*)(int)类型的函数指针
//该函数指针指向的函数参数是int,返回类型是void
//
//signal函数的返回类型也是一个函数指针
//该函数指针指向的函数参数是int,返回类型是void
//
//void (* signal(int, void(*)(int)))(int)
return 0;
}
上述的代码是一个函数的声明
函数的名字是signal
signal函数的参数第一个是int类型,第二个是void(*)(int)类型的函数指针
该函数指针指向的函数参数是int,返回类型是void
signal函数的返回类型也是一个函数指针
该函数指针指向的函数参数是int,返回类型是void
数组是一个存放相同类型数据的存储空间,那我们已经学习了指针数组,
比如:
int *arr[10];
//数组的每个元素是int*
那要把函数的地址存到一个数组中,那这个数组就叫函数指针数组,那函数指针的数组如何定义呢?
int (*parr1[10])();
int *parr2[10]();
int (*)() parr3[10];
答案是:parr1
parr1 先和 [] 结合,说明 parr1是数组,数组的内容是什么呢?
是 int (*)() 类型的函数指针。
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int Mul(int x, int y)
{
return x * y;
}
int Div(int x, int y)
{
return x / y;
}
int main()
{
//存放函数指针的数组 - 函数指针数组
int (* pf[4])(int, int) = {Add, Sub, Mul, Div};
//0 1 2 3
int i = 0;
for (i = 0; i < 4; i++)
{
int ret = pf[i](8, 4);
printf("%d\n", ret);
}
return 0;
}
函数指针数组的用途:转移表
例子:(计算器)
先写一个冗余的计算器
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int Mul(int x, int y)
{
return x * y;
}
int Div(int x, int y)
{
return x / y;
}
//写一个计算器能完成整数的+-*/
//增加: << >> & | ^ && ||
//
void menu()
{
printf("******************************\n");
printf("**** 1. add 2.sub *****\n");
printf("**** 3. mul 4.div *****\n");
printf("**** 0. exit *****\n");
printf("******************************\n");
}
int main()
{
int input = 0;
int x = 0;
int y = 0;
int ret = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("请输入两个操作数:>");
scanf("%d %d", &x, &y);
ret = Add(x, y);
printf("%d\n", ret);
break;
case 2:
printf("请输入两个操作数:>");
scanf("%d %d", &x, &y);
ret = Sub(x, y);
printf("%d\n", ret);
break;
case 3:
printf("请输入两个操作数:>");
scanf("%d %d", &x, &y);
ret = Mul(x, y);
printf("%d\n", ret);
break;
case 4:
printf("请输入两个操作数:>");
scanf("%d %d", &x, &y);
ret = Div(x, y);
printf("%d\n", ret);
break;
case 0:
printf("退出计算器\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
使用函数指针数组的实现:
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int Mul(int x, int y)
{
return x * y;
}
int Div(int x, int y)
{
return x / y;
}
//写一个计算器能完成整数的+-*/
//增加: << >> & | ^ && ||
//
void menu()
{
printf("******************************\n");
printf("**** 1. add 2.sub *****\n");
printf("**** 3. mul 4.div *****\n");
printf("**** 0. exit *****\n");
printf("******************************\n");
}
int main()
{
int input = 0;
int x = 0;
int y = 0;
int ret = 0;
//转移表 - 函数指针的数组
int (*pfArr[])(int, int) = { NULL, Add, Sub, Mul, Div };
//0 1 2 3 4
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
if (input == 0)
{
printf("退出计算器\n");
break;
}
else if (input >= 1 && input <= 4)
{
printf("请输入两个操作数:>");
scanf("%d %d", &x, &y);
ret = pfArr[input](x, y);
printf("%d\n", ret);
}
else
{
printf("选择错误\n");
}
} while (input);
return 0;
}
指向函数指针数组的指针是一个 指针
指针指向一个 数组 ,数组的元素都是 函数指针 ;
如何定义?
void test(const char* str)
{
printf("%s\n", str);
}
int main()
{
//函数指针pfun
void (*pfun)(const char*) = test;
//函数指针的数组pfunArr
void (*pfunArr[5])(const char* str);
pfunArr[0] = test;
//指向函数指针数组pfunArr的指针ppfunArr
void (*(*ppfunArr)[5])(const char*) = &pfunArr;
return 0;
}
再举了一个例子:
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int main()
{
int (*pf)(int, int) = Add;
//函数指针数组
int (* pfArr[4])(int, int) = {Add, Sub};
//
int (*(* ppfArr)[4])(int, int) = &pfArr;//ppfArr是一个指向函数指针数组的指针变量
return 0;
}
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
拿一下刚刚的计算器代码来优化讲解一下回调函数:
#include <stdio.h>
int Add(int x, int y)//回调函数
{
return x + y;
}
int Sub(int x, int y)//回调函数
{
return x - y;
}
int Mul(int x, int y)//回调函数
{
return x * y;
}
int Div(int x, int y)//回调函数
{
return x / y;
}
//写一个计算器能完成整数的+-*/
//增加: << >> & | ^ && ||
//
void menu()
{
printf("******************************\n");
printf("**** 1. add 2.sub *****\n");
printf("**** 3. mul 4.div *****\n");
printf("**** 0. exit *****\n");
printf("******************************\n");
}
void Calc(int(*pf)(int, int))
{
int x = 0;
int y = 0;
int ret = 0;
printf("请输入两个操作数:>");
scanf("%d %d", &x, &y);
ret = pf(x, y);
printf("%d\n", ret);
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
Calc(Add);
break;
case 2:
Calc(Sub);
break;
case 3:
Calc(Mul);
break;
case 4:
Calc(Div);
break;
case 0:
printf("退出计算器\n");
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
此时代码上面标注的就是回调函数。
图片展示过程:


如果这份博客对大家有帮助,希望各位给恒川一个免费的点赞作为鼓励,并评论收藏一下,谢谢大家!!!
制作不易,如果大家有什么疑问或给恒川的意见,欢迎评论区留言。
下一期要用到sqort库函数来讲解回调函数,希望大家期待一下!
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------
嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来
>>a=5=>5>>b=a=>5>>b=4=>4>>a=>5如何将“b”设置为实际的“a”,以便在示例中,变量a也将变为4。谢谢。 最佳答案 classRefdefinitializeval@val=valendattr_accessor:valdefto_s@val.to_sendenda=Ref.new(4)b=aputsa#=>4putsb#=>4a.val=5putsa#=>5putsb#=>5当您执行b=a时,b指向与a相同的对象(它们具有相同的object_id).当你执行a=some_other_thing时,a将指向
关闭。这个问题是off-topic.它目前不接受答案。想改进这个问题吗?Updatethequestion所以它是on-topic用于堆栈溢出。关闭11年前。Improvethisquestion我不经常使用ruby-通常它加起来相当于每两个月或更长时间编写一次脚本。我的大部分编程都是使用C++进行的,这与ruby有很大不同。由于我与ruby之间的差距如此之大,我总是忘记语言的基本方面(比如解析文本文件和其他简单的东西)。我想每天练习一些基本的东西,我想知道是否有一些我可以订阅的网站,并且会向我发送当天的Ruby问题或类似的东西。有人知道这样的站点/Internet服务吗?
如果特定语言环境中缺少翻译,如何配置i18n以使用en语言环境翻译?当前已插入翻译缺失消息。我正在使用RoR3.1。 最佳答案 找到相似的question这里是答案:#application.rb#railswillfallbacktoconfig.i18n.default_localetranslationconfig.i18n.fallbacks=true#railswillfallbacktoen,nomatterwhatissetasconfig.i18n.default_localeconfig.i18n.fallback
在我的双语Rails4应用程序中,我有一个像这样的LocalesController:classLocalesController用户可以通过此表单更改其语言环境:deflocale_switcherform_tagurl_for(:controller=>'locales',:action=>'change_locale'),:method=>'get',:id=>'locale_switcher'doselect_tag'set_locale',options_for_select(LANGUAGES,I18n.locale.to_s)end这有效。但是,目前用户无法通过URL更改
我使用Ruby编程已经有一段时间了,现在只使用Ruby的标准MRI实现,但我一直对我经常听到的其他实现感到好奇。前几天我在读有关Rubinius的文章,这是一个用Ruby编写的Ruby解释器。我试着在不同的地方查找它,但我很难弄清楚这样的东西到底是如何工作的。我在编译器或语言编写方面从来没有太多经验,但我真的很想弄明白。一门语言究竟如何才能被自己解释?编译中是否有一个我不明白这有意义的基本步骤?有人可以像我是个白痴一样向我解释这个吗(因为无论如何这都不会太离谱) 最佳答案 它比你想象的要简单。Rubinius并非100%用Ruby编
Ruby是完全面向对象的语言。在ruby中,一切都是对象,因此属于某个类。例如5属于Objectclass1.9.3p194:001>5.class=>Fixnum1.9.3p194:002>5.class.superclass=>Integer1.9.3p194:003>5.class.superclass.superclass=>Numeric1.9.3p194:005>5.class.superclass.superclass.superclass=>Object1.9.3p194:006>5.class.superclass.superclass.superclass.su