科学的本质是什么有什么用

Posts - 554,
Articles - 271,
Comments - 1000
白首为功名。旧山松竹老,阻归程。欲将心事付瑶琴。知音少,弦断有谁听?
00:05 by Rollen Holt, ... 阅读,
在大学的时候,教材里这么说的&引用是个别名...引用作为目标的别名而使用...引用不是值不占存储空间...引用只有声明,没有定义...&那么,引用到底占不占内存空间,引用的本质是什么?
下面举个例子:int a = 10;int &b =
这里,显然,b是一个引用。语句&int a = 10;&,在内存中申请了一个int型变量,32位机中占4个字节,那么变量名a放哪里了呢,有些人可能会有这个疑问。其实a代表的是一个内存地址,you know,计算机访问内存中的数据,全部是通过地址进行访问(这个结论你可以从《汇编》的寻址方式中得出)。在编译器将你的代码生成目标文件时,它会用这个地址替代所有的a,因此目标文件中也就没有变量名a了,所以,变量名a不会占用内存也就理所当然了。那么,引用 b会不会占内存空间呢?由于受大学课本的影响(引用b只是a的别名,b其实就是a本身),我很自然的会想到,b跟a一样,在编译后,所有的b也都用a的这个地址去替代,所以b也不会占用任何内存空间。前段时间,这个问题在快速入门群和高级专业群中各位朋友讨论了一下,大家也众说纷纭。在网上也搜到很多帖子,说引用只是一个别名,它不会占用空间。BUT,与各位高手的交流,查看众多网站,最后得出的结论是:&&&引用的本质是指针,而且是常量指针,占用4个字节的空间也就是说,&int &b =&会开辟一块4个字节的空间,用于存放那个地址,当然,变量名b不会占用空间。如果你听糊涂了,没关系,记住一条:引用b,本质就是一个常量指针(当然使用时不同)
下面是网络上比较权威的说法;另外,还有都史用于验证引用占内存的实例。如果大家有什么异议,本人希望与大家多多交流。
探索c++的底层机制
在看这篇文章之前,请你先要明白一点:那就是c++为我们所提供的各种存取控制仅仅是在编译阶段给我们的限制,也就是说是编译器确保了你在完成任务之前的正确行为,如果你的行为不正确,那么你休想构造出任何可执行程序来。但如果真正到了产生可执行代码阶段,无论是c,c++,还是pascal,大家都一样,你认为c和c++编译器产生的机器代码会有所不同吗,你认为c++产生的机器代码会有访问限制吗?那么你错了。什么const,private,统统没有(const变量或许会放入只读数据段),它不会再给你任何的限制,你可以利用一切内存修改工具或者是自己写一个程序对某一进程空间的某一变量进行修改,不管它在你的印象中是private,还是public,对于此时的你来说都一样,想怎样便怎样。另外,你也不要为c++所提供的什么晚期捆绑等机制大呼神奇,它也仅仅是在所产生的代码中多加了几条而已,它远没有你想象的那么智能,所有的工作都是编译器帮你完成,真正到了执行的时候,计算机会完全按照编译器产生的代码一丝不苟的执行。你明白我在说什么吗?对了,如果你从前接触过汇编,只要你反汇编一段c++代码,你就会说:原来是这么回事呀,c++只不过是把我们的问题进行了更高层次的抽象,但只要你解开面纱,回到问题的本源,一切都将变得不再神秘&&(以下的反汇编代码均来自visial c++ 7.0)&一.让我们从变量开始-----并非你想象的那么简单变量是什么,变量就是一个在程序执行过程中可以改变的量。换一个角度,变量是一块内存区域的名字,它就代表这块内存区域,当我们对变量进行修改的时候,会引起内存区域中内容的改变。但是你若是学习过汇编或是计算机组成原理,那么你就会清楚对于一块内存区域来说,根本就不存在什么名字,它所仅有的标志就是他的地址,因此我们若想修改一块内存区域的内容,只有知道他的地址方能实现。看来所谓的变量一说只不过是编译器给我们进行的一种抽象,让我们不必去了解更多的细节,降低我们的思维跨度而已。例如下面这条语句:int a=10;按照我们的思维习惯来讲,就是&存在一个变量a,它的值是10&,一切都显得那么的自然。我们不必去在乎什么所谓的地址以及其他的一些细节。然而在这条语句的底层实现中,a已经不能算是一个变量了,它仅仅是一个标记,代表一个地址的标记:mov dword ptr[a],0Ah;怎么样,这条语句不像上面那条易于接受吧,因为它需要了解更多的细节,你几乎不能得到编译器的任何帮助,一切思维上的跨越必须由你自己完成。这条语句应该解释为&把10写入以a为地址的内存区域&。你说什么?a有些像指针?对,的确像,但还不是,只不过他们的过程似乎是类似的。这里所说的跨越实际上就是从一个现实问题到具体地址以及内存区域的跨越。二.引用:你可以拥有引用,但编译器仅拥有指针(地址)看过了第一条,你一定对编译器的工作有了一定的了解,实际上编译器就是程序员与底层之间的一个转换层,它把一个高级语言代码转换为低级语言代码,一个编译器完成的转换跨度越大,那么它也就会越复杂,因为程序员的工作都由他代为完成了。C++编译器必然比汇编编译器复杂就是这个道理。如果我问你引用和指针是一样的吗?你或许会说当然不一样了,指针容易产生不安全的因素,引用却不会,真的不会吗?我们来看下面这段代码:int *e=new int(10);int &f=*e;f=30;你认为上面这段代码怎么样,我感觉就不很安全,它和指针有相同的隐患。因为它所引用的内存区域就不合法。我个人认为,所谓的引用其实就是一种指针,只不过二者的接口并不相同,引用的接口有一定的限制。指针可以一对多,而引用却只能一对一,即&refer不能被改变,但却并不能说一对一就是安全的,只不过危险的系数降低罢了。引用比指针更容易控制。Ok,下面来说说指针,曾经有过汇编经验的人一定会说,恩,指针的某些地方有些像汇编,尤其是那个&*&,怎么就那么像汇编中的&[]&啊。呵呵,的确,它也涵盖了一个寻址的过程。看来指针的确是个比较低级的东西。然而引用却并不那么直接,虽然程序员用起来方便安全了许多。但是你要清楚,只有你可以拥有引用,编译器可没有这个工具,计算机并不认识这个东西。因此,它的底层机制实际上是和指针一样的。不要相信只有一块内存拷贝,不要认为引用可以为你节省一个指针的空间,因为这一切不会发生,编译器还是会把引用解释为指针。不管你相不相信,请看下面这段代码:int& b=a;lea eax,[a];mov dword ptr[b],把a的地址赋给地址为b的一块内存
b=50;mov eax,dword ptr[b];mov dword ptr[eax],32h;
int *d=&a;lea eax,[a];mov dword ptr[d],eax
*d=60;mov eax,dword ptr[d]mov dword ptr[eax],3以上的代码均来自具体的编译器,怎么样,相信了吧,好,让我再来做一个或许不怎么恰当的比拟,你一定编过有关线性表和栈的程序吧,线性表是一个非常灵活的数据结构,在他上面有许多的操作,然而栈呢,它是一个限制性操作的线性表,它的底层操作实际上是由线性表操作实现的。就好比stack与vector的关系,因此指针和引用的关系就好比线性表和栈的关系,引用也就是受限的指针,它对外的接口和指针虽然并不一样,但底层是相同的。下面再来看看引用的一个重要用途,作为函数的参数传递的时候是怎样的情形:void swapr(int &a, int &b);void swapr(int* a, int *b);
int a=10;int b=20;
swapr(a, b);lea eax,[a];& //把a的地址压入堆栈lea ecx,[b];
swapr(&a, &b);lea eax,[a];lea ecx,[b];怎么样,用引用和指针传递参数无论是在效率上还是在空间上都是完全一样的,如果妄想不传入地址就修改实参的值,简直就是天方夜谭,这就说明引用的本质就是指针。毕竟它们的行为都太相似了,如果不是这样,你还有什么方法去实现引用吗?记住,引用只不过是编译器为你提供的一个有用且安全的工具,对于机器代码可无法表示它,它把指针一对多的缺点去除,禁止了你的不安全的操作。但回到问题的本源,他们没有任何区别。
都史的实例:
#include &iostream.h&
class A {double *m_pDb;};
class B {double &m_public:B(double db = 0) : m_db(db) {}};
int main() {cout && "size of class A:"&&sizeof(A) &&cout && "size of class B:"&&sizeof(B) &&return 0;}
size of class A:4
size of class B:4查看: 3764|回复: 12
中断的本质是什么
主题帖子积分
王道论坛初级道友, 积分 75, 距离下一级还需 125 积分
王道论坛初级道友, 积分 75, 距离下一级还需 125 积分
报考学校NJU
本科学校安徽理工
洗澡的时候不知怎么突然又想到“中断”。
以前上学的时候就听的就不是很明白,许多书里也讲的似是而非,在后来编程的时候又遇到很多名词像addListener,bind,槽,回调,事件,消息等等似乎都跟“中断”这个词有关。所以也上网看过许多帖子的解释,过程虽然很清晰明了,但是总觉得还是哪里隔着一层膜,让人那么的不舒服。
经常性的解释就是:loop {&&check A&&//假设check实在检查某事件是否发生&&do B&&check C&&do D}
在B执行时,如果C发生了,C不能得到及时相应,或者A一直不发生却一直检查A效率很低。
用中断机制时,loop {&&do B&&do D}
A,C发生了会主动发出信号,CPU再去处理。之前注册的两个回调
do B {}实际上,在底层,CPU执行完每条指令时都会去检查一个中断标志位,当发现某一位置1(可能)时,知道有中断发生(不考虑多中断),CPU会保存现场(context),转而执行我们提前注册过的程序,即ISR(Interrupt Service Routine),实际就是一种回调函数。ISR会调用具体硬件驱动程序的中断例程,这里的中断例程又是一种回调(linux会用request_irq注册),它会去读硬件寄存器取得事件的具体信息。之后的就不太熟悉了,猜测的,希望有高人教我
Linux可能会是层层回调机制,最上层的应用程序注册的回调最终会被调用。
windows可能用的事件机制(消息机制,一回事),事件从底层层层上传,windows窗口程序有一个线程专门循环GetMessage,检查一个事件队列。不管怎么样,检查某个事件是否发生本质都是轮询+check,它没在代码里看到,只是发生在别的地方了,比如CPU层级;或者换了一种方式。经常举得例子里实际是用听力代替了视力去轮询(觉得这里有什么可以挖掘,还没想到),一定范围内,听力比视力的监察范围更广。所谓的实时性,就是提高到了指令周期级别。每秒十亿次,但是在无限细分下去,仍然有无法响应的盲点,因为每一周期就是一个轮询。并行性也就是利用计算机极快的速度与人的反应的差别。并不是一直在运行,但是看上去似乎是的。光速30万公里每秒,人的肉眼捕捉不到24帧以下的空隙,当有那么快的速度时,人就可以做到分身术了
主题帖子积分
王道论坛初级道友, 积分 54, 距离下一级还需 146 积分
王道论坛初级道友, 积分 54, 距离下一级还需 146 积分
考研年份2013
报考学校华中科大
本科学校武汉科技学院
&listen&;
主题帖子积分
王道论坛初级道友, 积分 68, 距离下一级还需 132 积分
王道论坛初级道友, 积分 68, 距离下一级还需 132 积分
本科学校重庆大学
& & 楼主理解的已经不错了。由于我的毕设是搞操作系统,所以对操作系统这块理解还行。其实,对于CPU来说,不可能主动去“关心”是否了中断,运用传统的polling机制,这对于CPU来说是一种浪费。对于中断来说,操作系统是与CPU一起提供了一种机制进行管理,即中断机制。中断的话,当中断发生时,
1)& & & & CPU在执行完当前程序的每一条指令后,都会去确认在执行刚才的指令过程中中断控制器(如:8259A)是否发送中断请求过来,如果有那么CPU就会在相应的时钟脉冲到来时从总线上读取中断请求对应的中断向量;
2)& & & &&&CPU根据得到的中断向量(以此为索引)到IDT中找到该向量对应的中断描述符,中断描述符里保存着中断服务例程的段选择子;
3)& & & & CPU使用IDT查到的中断服务例程的段选择子从GDT中取得相应的段描述符,段描述符里保存了中断服务例程的段基址和属性信息,此时CPU就得到了中断服务例程的起始地址,并跳转到该地址;
4)& & & & CPU会根据CPL和中断服务例程的段描述符的DPL信息确认是否发生了特权级的转换。比如当前程序正运行在用户态,而中断程序是运行在内核态的,则意味着发生了特权级的转换,这时CPU会从当前程序的TSS信息(该信息在内存中的起始地址存在TR寄存器中)里取得该程序的内核栈地址,即包括内核态的ss和esp的值,并立即将系统当前使用的栈切换成新的内核栈。这个栈就是即将运行的中断服务程序要使用的栈。紧接着就将当前程序使用的用户态的ss和esp压到新的内核栈中保存起来;
5)& & & & CPU需要开始保存当前被打断的程序的现场(即一些寄存器的值),以便于将来恢复被打断的程序继续执行。这需要利用内核栈来保存相关现场信息,即依次压入当前被打断程序使用的eflags,cs,eip,errorCode(如果是有错误码的异常)信息;
6)& & & && &CPU利用中断服务例程的段描述符将其第一条指令的地址加载到cs和eip寄存器中,开始执行中断服务例程。这意味着先前的程序被暂停执行,中断服务程序正式开始工作。
当中断结束时,
1)& & & & 程序执行这条iret指令时,首先会从内核栈里弹出先前保存的被打断的程序的现场信息,即eflags,cs,eip重新开始执行;
2)& & & & 如果存在特权级转换(从内核态转换到用户态),则还需要从内核栈中弹出用户态栈的ss和esp,这样也意味着栈也被切换回原先使用的用户态的栈了;
3)& & & & 如果此次处理的是带有错误码(errorCode)的异常,CPU在恢复先前程序的现场时,并不会弹出errorCode。这一步需要通过软件完成,即要求相关的中断服务例程在调用iret返回之前添加出栈代码主动弹出errorCode。
下面的图解以我毕设中的xv6操作系统基础平台作为说明:trap.S为相关寄存器处理处,含有一个alltraps,而trap.c则是具体处理中断的地方。当然,这里并未绘制出中断所有的图解。
& && &IDT& && && && && && & trap.S& && && && && && && &&&trap.c
+----------------+& && && && && && && && &
|& &&handler1& & |---------& handler1:& && && & trap (struct Trapframe *tf)
|& && && && && & |& && && && & // do stuff& && && && && & {
|& && && && && & |& && && && & call trap& && && && && &&&// handle the exception/interrupt
|& && && && && & |& && && && & // undo stuff& && && &&&}
+----------------+
|& &&handler2& & |--------& handler2:
|& && && && && & |& && && && &// do stuff
|& && && && && & |& && && && &call trap
|& && && && && & |& && && && &// undo stuff
+----------------+
+----------------+
|& &&handlerX& & |--------& handlerX:
|& && && && && & |& && && && & // do stuff
|& && && && && & |& && && && & call trap
|& && && && && & |& && && && & // undo stuff
OK!中断大约就是这样,希望对楼主有帮助!
主题帖子积分
考研年份2013
报考学校北京邮电大学
本科学校武汉工大
我从来不去想中断的本质是什么这类抽象而又乏味的问题,就好像马克思主义的原理这种无聊的问题,我只考虑中断用在什么地方,怎么用,怎么用数学语言或者编程语言去实现中断的功能。
主题帖子积分
王道论坛初级道友, 积分 75, 距离下一级还需 125 积分
王道论坛初级道友, 积分 75, 距离下一级还需 125 积分
报考学校NJU
本科学校安徽理工
& &呵呵 你是应用派 但有的人喜欢寻根追底
主题帖子积分
王道论坛初级道友, 积分 75, 距离下一级还需 125 积分
王道论坛初级道友, 积分 75, 距离下一级还需 125 积分
报考学校NJU
本科学校安徽理工
BlueRomantic
& &你对操作系统这块了解不错哦,但是我想讨论问题的焦点在与你说的第一条& &1.CPU在执行完当前程序的每一条指令后,都会去确认在执行刚才的指令过程中中断控制器(如:8259A)是否发送中断请求过来,如果有那么CPU就会在相应的时钟脉冲到来时从总线上读取中断请求对应的中断向量;
如果cpu去确认是否有中断发过来,那么这就是一个轮询。整个指令周期包括中断周期
主题帖子积分
王道论坛初级道友, 积分 68, 距离下一级还需 132 积分
王道论坛初级道友, 积分 68, 距离下一级还需 132 积分
本科学校重庆大学
本帖最后由 BlueRomantic 于
22:26 编辑
& & 因为我的本科毕设就是给我们学院的大三和研究生设计操作系统实验,所以理解还行。对于你说的这个,我想我给你举一个例子吧,对于中断机制来说,假设你现在正在看影片,突然一个电话打过来了,你很自然的反应就是暂停影片,然后去接电话,接完电话后,再回过头来继续看影片。如果是polling机制的话,你就会每次都看电话一眼,看是不是有电话响起来,Hey man,你不觉得这太浪费资源了吗?其实完全可以等到电话铃声响的时候去处理就好了,而这个铃音就是中断信号的发出。同样的,就如同我此刻敲的键盘一样,每一次敲击都是键盘中断,那么万一我长时间不用键盘,只是用鼠标,那么CPU每一次都来守着键盘,看是不是键盘输入了,这多浪费~所以,只要你发一个键盘中断信号给我,在特定的时间脉冲片,CPU去处理就好了。于是,结论就是:CPU不会去主动“关心”中断,是中断找CPU~楼主,这下应该懂了吧?
主题帖子积分
王道论坛初级道友, 积分 75, 距离下一级还需 125 积分
王道论坛初级道友, 积分 75, 距离下一级还需 125 积分
报考学校NJU
本科学校安徽理工
BlueRomantic
& &你在看电影没有去检查只是表面,实际上你的听觉系统一直在轮询周围的环境,轮询并不是没有发生,之是换了一种方式。
主题帖子积分
王道论坛初级道友, 积分 68, 距离下一级还需 132 积分
王道论坛初级道友, 积分 68, 距离下一级还需 132 积分
本科学校重庆大学
首先,我建议楼主可以阅读以下Modern Operating Systems这本书,你会发现更详尽的解释!接下来我再说我的解释。
我想你的思维已经马上要走偏了。对于如今的操作系统来说,每一个外设中断机制硬件结构图是如下的:
各类设备&---&中断控制器&---&CPU
CPU监测的永远不会是各类中断,比如键盘中断、打印机中断等。如果真要这样监测,再强的CPU都会爆掉。
就如同你所说的听力系统在轮询周围环境,那么我们的听力系统要轮询多少范围的环境才能满足要求啊?你的听力系统也不用干其他事情了,就不停地轮询吧。
你的设备引起的中断需要有中断控制器才能传达给CPU,这是CPU主动去关心设备吗?不是的,如果中断控制器没有传达信号过来,CPU根本就不会理设备做什么了。
CPU看的是中断控制器这个东西(在我第一次给你回复的时候,中断开始的第1条就已经有了),而不是各类设备!
比如Linux源代码:
1,设备响应中断:
* struct irqaction - per interrupt action descriptor
* @handler:&&interrupt handler function
* @flags:&&flags (see IRQF_* above)
* @name:&&name of the device
* @dev_id:&&cookie to identify the device
* @next:&&pointer to the next irqaction for shared interrupts
* @irq:&&interrupt number
* @dir:&&pointer to the proc/irq/NN/name entry
* @thread_fn:&&interupt handler function for threaded interrupts
* @thread:&&thread pointer for threaded interrupts
* @thread_flags:flags related to @thread
struct irqaction {
irq_handler_
void *dev_
struct irqaction *
irq_handler_t thread_
struct task_struct *
unsigned long thread_
const char *
struct proc_dir_entry *
} ____cacheline_internodealigned_in_
请注意,还有1个中断控制器:
2,中断控制器
struct irq_chip {
const char&&*
unsigned int&&(*startup)(unsigned int irq);
void (*shutdown)(unsigned int irq);
void (*enable)(unsigned int irq);
void (*disable)(unsigned int irq);
void (*ack)(unsigned int irq);
void (*mask)(unsigned int irq);
void (*mask_ack)(unsigned int irq);
void (*unmask)(unsigned int irq);
void (*eoi)(unsigned int irq);
void (*end)(unsigned int irq);
int (*set_affinity)(unsigned int irq,
const struct cpumask *dest);
int (*retrigger)(unsigned int irq);
int (*set_type)(unsigned int irq, unsigned int flow_type);
int (*set_wake)(unsigned int irq, unsigned int on);
3.CPU是如何组织管理各个中断的呢?内核通过一个全局变量struct irq_desc irq_desc[NR_IRQS]对系统的中断进行管理,每个中断号
对应一个irq_desc[irq], struct irq_desc定义如下:
struct irq_desc {
struct irq_chip*
void *handler_
void *chip_
irq_flow_handler_thandle_
struct irqaction*/* IRQ action list */
unsigned int&& /* IRQ status */
unsigned int&& /* nested irq disables */
unsigned int&&irq_ /* For detecting broken IRQs */
} ____cacheline_internodealigned_in_
可见,对于每一个中断,这里包含了中断处理程序,状态,统计值等。系统状态信息可通过如下命令查询:cat /proc/interrupts
相关的中断处理代码:
entry_64.S: 中断入口,汇编部分的处理。
irq.c:do_IRQ函数是中断处理的通用C代码,这里最终会调用到各个设备的中断处理函数。
void (*bus_lock)(unsigned int irq);
void (*bus_sync_unlock)(unsigned int irq);
主题帖子积分
考研年份2013
报考学校合肥工大
本科学校合肥师范学院
不错 中断的概念不必要深究&&要的就是中断时的具体操作 考试会考
主题帖子积分
王道论坛初级道友, 积分 75, 距离下一级还需 125 积分
王道论坛初级道友, 积分 75, 距离下一级还需 125 积分
报考学校NJU
本科学校安徽理工
BlueRomantic
& &no,no,no 我没说对每一个外设啊,不管有多少外设。关键在于cpu如何察觉到信号的。人坐在那里看电影如何知道周围发生了什么。表面上你把注意力集中到电影上了,你把耳朵堵住能发现其它事么?
主题帖子积分
王道论坛初级道友, 积分 75, 距离下一级还需 125 积分
王道论坛初级道友, 积分 75, 距离下一级还需 125 积分
报考学校NJU
本科学校安徽理工
本帖最后由 lcqtdwj 于
19:35 编辑
BlueRomantic
& &实际就是说,cpu在执行完一个指令或者一个周期后回去检查中断控制器有没有发送电信号过来。这是一个完整的循环周期。这是硬件完成的,但仍然是一种编程,电路编程。人类设计好的循环流程。要想知道一件事有没有发生,只有一条途径,就是去看(或者其他方式,听)。
主题帖子积分
考研年份2014
报考学校武汉大学
本科学校上海大学
& & 校友好!!
Powered by Discuz!本质和实质有什么区别_百度知道
本质和实质有什么区别
政治的本质是经济的集中表现他的实质阶级关系和阶级斗争 到底他本质和实质是怎么样区分的 谢
是通过现象来表现的。实质。 本质 。决定事物性质:指事物本身所固有的,必须透过现象掌握本质,不能用简单的直观去认识。事物的本质是隐蔽的、面貌和发展的根本属性本质加实质就是未来: 本质 性质 一种事物区别于其他事物的根本属性
其他类似问题
为您推荐:
其他1条回答
本质和实质的含义是一样的,在用不同视角看一件事物内部时加重表达力。
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁EntitySet&T&与EntityList&T&到底有什么本质区别?各自最恰当的使用场合是?
[问题点数:80分,结帖人xhtmldivcss]
EntitySet&T&与EntityList&T&到底有什么本质区别?各自最恰当的使用场合是?
[问题点数:80分,结帖人xhtmldivcss]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2010年7月 扩充话题大版内专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。

我要回帖

更多关于 法的本质是什么 的文章

 

随机推荐