c++指针用法简介

c++指针用法简介
c++指针用法简介

1.语言中变量的实质

要理解C指针,我认为一定要理解C中“变量”的存储实质,所以我就从“变量”这个东西开始讲起吧!

先来理解理解内存空间吧!请看下图:

内存地址→ 6 78 910 11 12 13

-----------------------------------------------------------------

。。。||||||||.。

-----------------------------------------------------------------

如图所示,内存只不过是一个存放数据的空间,就好像我的看电影时的电影院中的座位一样。每个座位都要编号,我们的内存要存放各种各样的数据,当然我们要知道我们的这些数据存放在什么位置吧!所以内存也要象座位一样进行编号了,这就是我们所说的内存编址。座位可以是按一个座位一个号码的从一号开始编号,内存则是按一个字节一个字节进行编址,如上图所示。每个字节都有个编号,我们称之为内存地址。好了,我说了这么多,现在你能理解内存空间这个概念吗?

我们继续看看以下的C、C++语言变量申明:

int I;

char a;

每次我们要使用某变量时都要事先这样申明它,它其实是内存中申请了一个名为i的整型变量宽度的空间(DOS下的16位编程中其宽度为二个字节),和一个名为a的字符型变量宽度的空间(占一个字节)。

我们又如何来理解变量是如何存在的呢。当我们如下申明变量时:

int I;

char a;

内存中的映象可能如下图:

内存地址→ 6 78 9 10 11 12 13

------------------------------------------------------------------

。。。||||||||.。

------------------------------------------------------------------

变量名|→i←|→a←|

图中可看出,i在内存起始地址为6上申请了两个字节的空间(我这里假设了int的宽度为16位,不同系统中int的宽度是可能不一样的),并命名为i. a在内存地址为8上申请了一字节的空间,并命名为a.这样我们就有两个不同类型的变量了。

2.赋值给变量

再看下面赋值:

i=30

a=‘t’

你当然知道个两个语句是将30存入i变量的内存空间中,将‘t’字符存入a变量的内存空间中。我们可以这样的形象理解啦:

内存地址→ 6 78 9 10 11 12 13

-----------------------------------------------------------------------

。。。|30 | ‘t’|||||.。

-----------------------------------------------------------------------

|→i←|→a←|

3.变量在哪里?(即我想知道变量的地址)

好了,接下来我们来看看&i是什么意思?

是取i变量所在的地址编号嘛!我们可以这样读它:返回i变量的地址编号。你记住了吗?

我要在屏幕上显示变量的地址值的话,可以写如下代码:

printf(“%d”,&i);

以上图的内存映象所例,屏幕上显示的不是i值30,而是显示i的内存地址编号6了。当然实际你操作的时,i变量的地址值不会是这个数了。

这就是我认为作为初学者们所应想象的变量存储实质了。请这样理解吧!

现在你可知道①、②两个printf分别在屏幕上输出的是i的什么东西啊?

好啦!下面我们就开始真正进入指针的学习了。Come on !(待续…).

二、指针是什么东西

想说弄懂你不容易啊!我们许多初学指针的人都要这样的感慨。我常常在思索它,为什么呢?其实生活中处处都有指针。我们也处处在使用它。有了它我们的生活才更加方便了。没有指针,那生活才不方便。不信?你看下面的例子。

这是一个生活中的例子:比如说你要我借给你一本书,我到了你宿舍,但是你人不在宿舍,于是我把书放在你的2层3号的书架上,并写了一张纸条放在你的桌上。纸条上写着:你要的书在第2层3号的书架上。当你回来时,看到这张纸条。你就知道了我借与你的书放在哪了。你想想看,这张纸条的作用,纸条本身不是书,它上面也没有放着书。那么你又如何知道书的位置呢?因为纸条上写着书的位置嘛!其实这张纸条就是一个指针了。它上面的内容不是书本身,而是书的地址,你通过纸条这个指针找到了我借给你的本书。

那么我们C,C++中的指针又是什么呢?请继续跟我来吧,看下面看一个申明一整型指针变量的语句如下:

int * pi;

pi是一个指针,当然我们知道啦,但是这样说,你就以为pi一定是个多么特别的东西了。其实,它也只过是一个变量而已。与上一篇中说的变量并没有实质的区别。不信你看下面图。

内存地址→678 9 10 11 12 13 14

--------------------------------------------------------------

...| 30 | ‘t’ || | | | | |……

--------------------------------------------------------------

变量|→i←|→a←||→ pi←|

(说明:这里我假设了指针只占2个字节宽度,实际上在32位系统中,指针的宽度是4个字节宽的,即32位。)由图示中可以看出,我们使用int *Pi申明指针变量;其实是在内存的某处申明一个一定宽度的内存空间,并把它命名为Pi.你能在图中看出pi与前面的i,a 变量有什么本质区别吗,没有,当然没有!pi也只不过是一个变量而已嘛!那么它又为什么会

被称为指针?关键是我们要让这个变量所存储的内容是什么。现在我要让pi成为真正有意义上的指针。请接着看下面语句:

pi=&i;

你应该知道&i是什么意思吧!再次提醒你啦:这是返回i变量的地址编号。整句的意思就是把i地址的编号赋值给pi,也就是你在pi上写上i的地址编号。结果如下图所示:内存地址→678910 11 12 13 14

------------------------------------------------------------------

...| 30 | ‘t’| | | 6 | | |……

------------------------------------------------------------------

变量|→i←|→a←||→ pi←|

你看,执行完pi=&i;后,在图示中的系统中,pi的值是6.这个6就是i变量的地址编号,这样pi就指向了变量i了。你看,pi与那张纸条有什么区别?pi不就是那张纸条嘛!上面写着i的地址,而i就是那个本书。你现在看懂了吗?因此,我们就把pi称为指针。所以你要记住,指针变量所存的内容就是内存的地址编号!好了,现在我们就可以通过这个指针pi 来访问到i这个变量了,不是吗?。看下面语句:

printf(“%d”,*pi);

那么*pi什么意思呢?你只要这样读它:pi内容所指的地址的内容(嘻嘻,看上去好像在绕口令了),就pi这张“纸条”上所写的位置上的那本“书”——i .你看,Pi内容是6,也就是说pi指向内存编号为6的地址。*pi嘛!就是它所指地址的内容,即地址编号6上的内容了。当然就是30的值了。所以这条语句会在屏幕上显示30.也就是说printf(“%d”,*pi);语句等价于printf(“%d”,i ),请结合上图好好体会吧!各位还有什么疑问,可以发Email:yyf977@https://www.360docs.net/doc/6e3219339.html,.

到此为止,你掌握了类似&i ,*pi写法的含义和相关操作吗。总的一句话,我们的纸条就是我们的指针,同样我们的pi也就是我们的纸条!剩下的就是我们如何应用这张纸条了。最后我给你一道题:

到这了。Happy to Study!在下篇中我将谈谈“指针的指针”即对int * * ppa;中ppa 的理解。

1.数组元素

很显然,它是显示a 数组的各元素值。

它的结果和作用完全一样

看pa=a即数组名赋值给指针,以及通过数组名、指针对元素的访问形式看,它们并没有什么区别,从这里可以看出数组名其实也就是指针。难道它们没有任何区别?有,请继续。

3. 数组名与指针变量的区别

可以看出,这段代码也是将数组各元素值输出。不过,你把{}中的pa改成a试试。你会发现程序编译出错,不能成功。看来指针和数组名还是不同的。其实上面的指针是指针变量,而数组名只是一个指针常量。这个代码与上面的代码不同的是,指针pa在整个循环中,其值是不断递增的,即指针值被修改了。数组名是指针常量,其值是不能修改的,因此不能类似这样操作:a++.前面4,5节中pa[i],*(pa+i)处,指针pa的值是使终没有改变。所以变量指针pa与数组名a可以互换。

4. 申明指针常量

再请看下面的代码:

这时候的代码能成功编译吗?不能。因为pa指针被定义为常量指针了。这时与数组名a已经没有不同。这更说明了数组名就是常量指针。但是…

int * const a={3,4,5,6,7,3,7,4,4,6};//不行

int a[]={3,4,5,6,7,3,7,4,4,6};//可以,所以初始化数组时必定要这样。

以上都是在VC6.0上实验。

1 int i 说起

你知道我们申明一个变量时象这样int i ;这个i是可能在它处重新变赋值的。如下:int i=0;

//…

i=20;//这里重新赋值了

不过有一天我的程序可能需要这样一个变量(暂且称它变量),在申明时就赋一个初始值。之后我的程序在其它任何处都不会再去重新对它赋值。那我又应该怎么办呢?用const .

//**************

const int ic =20;

//…

ic=40;//这样是不可以的,编译时是无法通过,因为我们不能对const 修饰的ic重新赋值的。

//这样我们的程序就会更早更容易发现问题了。

//**************

有了const修饰的ic 我们不称它为变量,而称符号常量,代表着20这个数。这就是const 的作用。ic是不能在它处重新赋新值了。

认识了const 作用之后,另外,我们还要知道格式的写法。有两种:const int ic=20;与int const ic=20;。它们是完全相同的。这一点我们是要清楚。总之,你务必要记住const 与int哪个写前都不影响语义。有了这个概念后,我们来看这两个家伙:const int * pi与int const * pi ,按你的逻辑看,它们的语义有不同吗?呵呵,你只要记住一点,int 与const 哪个放前哪个放后都是一样的,就好比const int ic;与int const ic;一样。也就是说,它们是相同的。

好了,我们现在已经搞定一个“双包胎”的问题。那么int * const pi与前两个式子又有什么不同呢?我下面就来具体分析它们的格式与语义吧!

2 const int * pi的语义

我先来说说const int * pi是什么作用(当然int const * pi也是一样的,前面我们说过,它们实际是一样的)。看下面的例子:

语义分析:

看出来了没有啊,pi的值是可以被修改的。即它可以重新指向另一个地址的,但是,不能通过*pi来修改i2的值。这个规则符合我们前面所讲的逻辑吗?当然符合了!

首先const 修饰的是整个*pi(注意,我写的是*pi而不是pi)。所以*pi是常量,是不能被赋值的(虽然pi所指的i2是变量,不是常量)。

其次,pi前并没有用const 修饰,所以pi是指针变量,能被赋值重新指向另一内存地址的。你可能会疑问:那我又如何用const 来修饰pi呢?其实,你注意到int * const pi中const 的位置就大概可以明白了。请记住,通过格式看语义。哈哈,你可能已经看出了规律吧?那下面的一节也就没必要看下去了。不过我还得继续我的战斗!

3 再看int * const pi

确实,int * const pi与前面的int const * pi会很容易给混淆的。注意:前面一句的const 是写在pi前和*号后的,而不是写在*pi前的。很显然,它是修饰限定pi的。我先让你看例子:

看了这段代码,你明白了什么?有没有发现pi值是不能重新赋值修改了。它只能永远指向初始化时的内存地址了。相反,这次你可以通过*pi来修改i1的值了。与前一个例子对照一下吧!看以下的两点分析

1)pi因为有了const 的修饰,所以只是一个指针常量:也就是说pi值是不可修改的(即pi不可以重新指向i2这个变量了)(看第4行)。

2)整个*pi的前面没有const 的修饰。也就是说,*pi是变量而不是常量,所以我们可以通过*pi来修改它所指内存i1的值(看5行的注释)

总之一句话,这次的pi是一个指向int变量类型数据的指针常量。

我最后总结两句:

1) 如果const 修饰在*pi前则不能改的是*pi(即不能类似这样:*pi=50;赋值)而不是指pi.

2) 如果const 是直接写在pi前则pi不能改(即不能类似这样:pi=&i;赋值)。

请你务必先记住这两点,相信你一定不会再被它们给搞糊了。现在再看这两个申明语句int const *pi和int * const pi时,呵呵,你会头昏脑胀还是很轻松惬意?它们各自申明的pi分别能修改什么,不能修改什么?再问问自己,把你的理解告诉我吧,可以发帖也可以发到我的邮箱(我的邮箱yyf977@https://www.360docs.net/doc/6e3219339.html,)!我一定会答复的。

3) 补充三种情况。

这里,我再补充以下三种情况。其实只要上面的语义搞清楚了,这三种情况也就已经被包含了。不过作为三种具体的形式,我还是简单提一下吧!

对x,y的操作就是对a,b的操作了,这是一个错误的观点啊!)。

一、三道考题开讲之前,我先请你做三道题目。(嘿嘿,得先把你的头脑搞昏才行……唉呀,谁扔我鸡蛋?)

输出的结果:

x=____,y=____

a=____,b=____

问下划线的部分应是什么,请完成。

输出的结果为:

*px=____,*py=____

a=____,b=____

问下划线的部分应是什么,请完成。

输出的结果:

x=____,y=____

a=____,b=____

问下划线的部分输出的应是什么,请完成。

你不在机子上试,能作出来吗?你对你写出的答案有多大的把握?

正确的答案,想知道吗?(呵呵,让我慢慢地告诉你吧!)

好,废话少说,继续我们的探索之旅了。

我们都知道:C语言中函数参数的传递有:值传递,地址传递,引用传递这三种形式。题一为值传递,题二为地址传递,题三为引用传递。不过,正是这几种参数传递的形式,曾把我给搞得晕头转向。我相信也有很多人与我有同感吧?

下面请让我逐个地谈谈这三种传递形式。

二、函数参数传递方式之一:值传递

1. 值传递的一个错误认识

问:你认为这个函数是在做什么呀?

答:好像是对参数x,y的值对调吧?

我问:Exchg1 ()里头的printf(“x=%d,y=%d\n”,x,y)语句会输出什么啊?

我再问:Exchg1 ()后的printf(“a=%d,b=%d\n”,a,b)语句输出的是什么?

程序输出的结果是:

x=6 ,y=4

a=4 ,b=6 //为什么不是a=6,b=4呢?

奇怪,明明我把a,b分别代入了x,y中,并在函数里完成了两个变量值的交换,为什么a,b变量值还是没有交换(仍然是a==4,b==6,而不是a==6,b==4)?如果你也会有这个疑问,那是因为你跟本就不知实参a,b与形参x,y的关系了。

2. 一个预备的常识

为了说明这个问题,我先给出一个代码:

int a=4;

int x;

x=a;

x=x+3;

看好了没,现在我问你:最终a值是多少,x值是多少?

(怎么搞的,给我这个小儿科的问题。还不简单,不就是a==4 x==7嘛!)

在这个代码中,你要明白一个东西:虽然a值赋给了x,但是a变量并不是x变量哦。我们对x任何的修改,都不会改变a变量。呵呵!虽然简单,并且一看就理所当然,不过可是一个很重要的认识喔。

3. 理解值传递的形式

请注意在调用执行Exchg1函数的操作中我人为地加上了头两句:

int x=a;

int y=b;

这是调用函数时的两个隐含动作。它确实存在,现在我只不过把它显式地写了出来而已。问题一下就清晰起来啦。(看到这里,现在你认为函数里面交换操作的是a,b变量或者只是x,y变量呢?)

原来,其实函数在调用时是隐含地把实参a,b 的值分别赋值给了x,y,之后在你写的Exchg1函数体内再也没有对a,b进行任何的操作了。交换的只是x,y变量。并不是a,b.当然a,b的值没有改变啦!函数只是把a,b的值通过赋值传递给了x,y,函数里头操作的只是x,y的值并不是a,b的值。这就是所谓的参数的值传递了。

哈哈,终于明白了,正是因为它隐含了那两个的赋值操作,才让我们产生了前述的迷惑(以为a,b已经代替了x,y,对x,y的操作就是对a,b的操作了,这是一个错误的观点啊!)。

指向另一指针的指针

一、针概念:

早在本系列第二篇中我就对指针的实质进行了阐述。今天我们又要学习一个叫做指向另一指针地址的指针。让我们先回顾一下指针的概念吧!

当我们程序如下申明变量:

short int i;

char a;

short int * pi;

程序会在内存某地址空间上为各变量开辟空间,如下图所示。

内存地址→678 9 10 11 12 13 14 15

-------------------------------------------------------------------------------------

…| |||||||||

-------------------------------------------------------------------------------------

|short int i |char a||short int * pi|

图中所示中可看出:

i 变量在内存地址5的位置,占两个字节。

a变量在内存地址7的位置,占一个字节。

pi变量在内存地址9的位置,占两个字节。(注:pi 是指针,我这里指针的宽度只有两个字节,32位系统是四个字节)

接下来如下赋值:

i=50;

pi=&i;

经过上在两句的赋值,变量的内存映象如下:

内存地址→678 9 10 11 12 1314 15

--------------------------------------------------------------------------------------

…| 50||| 6||||

--------------------------------------------------------------------------------------

|short int i |char a||short int * pi|

看到没有:短整型指针变量pi的值为6,它就是I变量的内存起始地址。所以,这时当我们对*pi进行读写操作时,其实就是对i变量的读写操作。如:

*pi=5;//就是等价于I=5;

你可以回看本系列的第二篇,那里有更加详细的解说。

二、指针的地址与指向另一指针地址的指针

在上一节中,我们看到,指针变量本身与其它变量一样也是在某个内存地址中的,如pi的内存起始地址是10.同样的,我们也可能让某个指针指向这个地址。

看下面代码:

short int * * ppi;//这是一个指向指针的指针,注意有两个*号

ppi=π

第一句:short int * * ppi;——申明了一个指针变量ppi,这个ppi是用来存储(或称指向)一个short int * 类型指针变量的地址。

第二句:&pi那就是取pi的地址,ppi=π就是把pi的地址赋给了ppi.即将地址值10赋值给ppi.如下图:

内存地址→678 9 10 11 12 1314 15

------------------------------------------------------------------------------------

…| 50 |||6|10||

------------------------------------------------------------------------------------

|short int i|char a||short int * pi|short int ** ppi|

从图中看出,指针变量ppi的内容就是指针变量pi的起始地址。于是……

ppi的值是多少呢?——10.

*ppi的值是多少呢?——6,即pi的值。

**ppi的值是多少呢?——50,即I的值,也是*pi的值。

呵呵!不用我说太多了,我相信你应明白这种指针了吧!

三、一个应用实例

1. 设计一个函数:void find1(char array[],char search,char * pi)

要求:这个函数参数中的数组array是以0值为结束的字符串,要求在字符串array中查找字符是参数search里的字符。如果找到,函数通过第三个参数(pa)返回值为array字符串中第一个找到的字符的地址。如果没找到,则为pa为0.

调试:

分析:

上面代码,你认为会是输出什么呢?

运行试试。

唉!怎么输出的是:没有找到!

而不是:找到了,……。

明明a值为‘d’,而str字符串的第四个字符是‘d’,应该找得到呀!

再看函数定义处:void find1(char [] array,char search,char * pa)

看调用处:find1(str,a,p);

依我在第五篇的分析方法,函数调用时会对每一个参数进行一个隐含的赋值操作。

哦!参数pa与参数search的传递并没有什么不同,都是值传递嘛(小语:地址传递其实就是地址值传递嘛)!所以对形参变量pa值(当然值是一个地址值)的修改并不会改变实参变量p值,因此p的值并没有改变(即p的指向并没有被改变)。

(如果还有疑问,再看一看《第五篇:函数参数的传递》了。)

主函数的调用处改如下:

find2(str,a,&p);//调用函数以实现所要操作。

再分析:

看明白了吗?

ppa指向指针p的地址。

对*ppa的修改就是对p值的修改。

你自行去调试。

经过修改后的程序就可以完成所要的功能了。

看懂了这个例子,也就达到了本篇所要求的目的。

函数名与函数指针

一数调用

这个MyFun函数是一个无返回值的函数,它并不完成什么事情。这种调用函数的格式你应该是很熟悉的吧!看主函数中调用MyFun函数的书写格式:

MyFun(10);

我们一开始只是从功能上或者说从数学意义上理解MyFun这个函数,知道MyFun函数名代表的是一个功能(或是说一段代码)。

直到——

学习到函数指针概念时。我才不得不在思考:函数名到底又是什么东西呢?

(不要以为这是没有什么意义的事噢!呵呵,继续往下看你就知道了。)

二函数指针变量的申明

就象某一数据变量的内存地址可以存储在相应的指针变量中一样,函数的首地址也以存储在某个函数指针变量里的。这样,我就可以通过这个函数指针变量来调用所指向的函数了。

在C系列语言中,任何一个变量,总是要先申明,之后才能使用的。那么,函数指针变量也应该要先申明吧?那又是如何来申明呢?以上面的例子为例,我来申明一个可以指向MyFun函数的函数指针变量FunP.下面就是申明FunP变量的方法:

void (*FunP)(int);//也可写成void (*FunP)(int x);

你看,整个函数指针变量的申明格式如同函数MyFun的申明处一样,只不过——我们把MyFun改成(*FunP)而已,这样就有了一个能指向MyFun函数的指针FunP了。(当然,这个FunP指针变量也可以指向所有其它具有相同参数及返回值的函数了。)三通过函数指针变量调用函数

有了FunP指针变量后,我们就可以对它赋值指向MyFun,然后通过FunP来调用MyFun 函数了。看我如何通过FunP指针变量来调用MyFun函数的:

请看黑体字部分的代码及注释。

运行看看。嗯,不错,程序运行得很好。

哦,我的感觉是:MyFun与FunP的类型关系类似于int 与int *的关系。函数MyFun 好像是一个如int的变量(或常量),而FunP则像一个如int *一样的指针变量。

int i,*pi;

pi=&i;//与FunP=&MyFun比较。

(你的感觉呢?)

呵呵,其实不然——

四调用函数的其它书写格式

函数指针也可如下使用,来完成同样的事情:

我改了黑体字部分(请自行与之前的代码比较一下)。

运行试试,啊!一样地成功。

咦?

FunP=MyFun;

可以这样将MyFun值同赋值给FunP,难道MyFun与FunP是同一数据类型(即如同的int 与int的关系),而不是如同int 与int*的关系了?(有没有一点点的糊涂了?)

看来与之前的代码有点矛盾了,是吧!所以我说嘛!

请容许我暂不给你解释,继续看以下几种情况(这些可都是可以正确运行的代码哟!):

代码之三:

真的是可以这样的噢!

(哇!真是要晕倒了!)

还有呐!看——

你也许第一次见到吧:函数名调用也可以是这样写的啊!(只不过我们平常没有这样书写罢了。)

那么,这些又说明了什么呢?

呵呵!依据以往的知识和经验来推理本篇的“新发现”,我想就连“福尔摩斯”也必定会由此分析并推断出以下的结论:

1. 其实,MyFun的函数名与FunP函数指针都是一样的,即都是函数指针。MyFun函数名是一个函数指针常量,而FunP是一个函数数指针变量,这是它们的关系。

2. 但函数名调用如果都得如(*MyFun)(10);这样,那书写与读起来都是不方便和不习惯的。所以C语言的设计者们才会设计成又可允许MyFun(10);这种形式地调用(这样方便多了并与数学中的函数形式一样,不是吗?)。

3. 为统一起见,FunP函数指针变量也可以FunP(10)的形式来调用。

4. 赋值时,即可FunP=&MyFun形式,也可FunP=MyFun.

上述代码的写法,随便你爱怎么着!

请这样理解吧!这可是有助于你对函数指针的应用喽!

最后——

补充说明一点:在函数的申明处:

void MyFun(int ); //不能写成void (*MyFun)(int )。

void (*FunP)(int ); //不能写成void FunP(int )。

(请看注释)这一点是要注意的。

五定义某一函数的指针类型:

就像自定义数据类型一样,我们也可以先定义一个函数指针类型,然后再用这个类型来申明函数指针变量。

我先给你一个自定义数据类型的例子。

根据注释,应该不难看懂吧!(虽然你可能很少这样定义使用,但以后学习Win32编程时会经常见到的。)

下面我们来看一下函数指针类型的定义及使用:(请与上对照!)

看黑体部分:

首先,在void (*FunType)(int );前加了一个typedef .这样只是定义一个名为FunType函数指针类型,而不是一个FunType变量。

然后,FunType FunP;这句就如PINT px;一样地申明一个FunP变量。

其它相同。整个程序完成了相同的事。

这样做法的好处是:

有了FunType类型后,我们就可以同样地、很方便地用FunType类型来申明多个同类型的函数指针变量了。如下:

FunType FunP2;

FunType FunP3;

//……

六函数指针作为某个函数的参数

既然函数指针变量是一个变量,当然也可以作为某个函数的参数来使用的。所以,你还应知道函数指针是如何作为某个函数的参数来传递使用的。

给你一个实例:

要求:我要设计一个CallMyFun函数,这个函数可以通过参数中的函数指针值不同来分别调用MyFun1、MyFun2、MyFun3这三个函数(注:这三个函数的定义格式应相同)。

实现:代码如下:

The way常见用法

The way 的用法 Ⅰ常见用法: 1)the way+ that 2)the way + in which(最为正式的用法) 3)the way + 省略(最为自然的用法) 举例:I like the way in which he talks. I like the way that he talks. I like the way he talks. Ⅱ习惯用法: 在当代美国英语中,the way用作为副词的对格,“the way+ 从句”实际上相当于一个状语从句来修饰整个句子。 1)The way =as I am talking to you just the way I’d talk to my own child. He did not do it the way his friends did. Most fruits are naturally sweet and we can eat them just the way they are—all we have to do is to clean and peel them. 2)The way= according to the way/ judging from the way The way you answer the question, you are an excellent student. The way most people look at you, you’d think trash man is a monster. 3)The way =how/ how much No one can imagine the way he missed her. 4)The way =because

“的、地、得”用法分析及练习(后附答案)

“的、地、得”用法分析及练习(后附答案) 一、的、地、得用法分析: “的”后面跟的都是表示事物名称的词或词语,如:敬爱的总理、慈祥的老人、戴帽子的男孩、珍贵的教科书、鸟的天堂、伟大的祖国、有趣的情节、优雅的环境、可疑的情况、团结友爱的集体、他的妈妈、可爱的花儿、谁的橡皮、清清的河水...... “地”后面跟的都是表示动作的词或词语,如:高声地喊、愉快地唱、拼命地逃、疯狂地咒骂、严密地注视、一次又一次地握手、迅速地包围、沙沙地直响、斩钉截铁地说、从容不迫地申述、用力地踢、仔细地看、开心地笑笑......” “得”前面多数是表示动作的词或词语,少数是形容词;后面跟的都是形容事物状态的词或词语,表示怎么怎么样的,如:走得很快、踩得稀烂、疼得直叫唤、瘦得皮包骨头、红得发紫、气得双脚直跳、理解得十分深刻、乐得合不拢嘴、惊讶得目瞪口呆、大得很、扫得真干净、笑得多甜啊...... 二、的、地、得用法补充说明: 1、如果“de”的后面是“很、真、太”等这些词,十有八九用“得”。 2、有一种情况,如“他高兴得一蹦三尺高”这句话里,后面的“一蹦三尺高”虽然是表示动作的,但是它是来形容“高兴”的程度的,所以也应该用“得”。

三、的、地、得用法总结: 1、“的”前面的词语一般用来修饰、限制“的”后面的事物,说明“的”后面的事物怎么样。结构形式一般为:修饰、限制的词语+的+名词。 2、“地”前面的词语一般用来形容“地”后面的动作,说明“地”后面的动作怎么样。结构方式一般为:修饰、限制的词语+地+动词。 3、“得”后面的词语一般用来补充说明“得”前面的动作怎么样,结构形式一般为:动词(形容词)+得+补充、说明的词语。 四、的、地、得用法例句: 1. 蔚蓝色的海洋,波涛汹涌,无边无际。 2. 向日葵在微风中向我们轻轻地点头微笑。 3. 小明在海安儿童公园玩得很开心。 五、“的、地、得”的读音: “的、地、得”是现代汉语中高频度使用的三个结构助词,都起着连接作用;它们在普通话中都各自有着各自的不同的读音,但当他们附着在词,短语,句子的前面或后面,表示结构关系或某些附加意义的时候都读轻声“de”,没有语音上的区别。 但在书面语中有必要写成三个不同的字,这样可以区分他们在书面语用法上的不同。这样做的好处,就是可使书面语言精确化。

The way的用法及其含义(二)

The way的用法及其含义(二) 二、the way在句中的语法作用 the way在句中可以作主语、宾语或表语: 1.作主语 The way you are doing it is completely crazy.你这个干法简直发疯。 The way she puts on that accent really irritates me. 她故意操那种口音的样子实在令我恼火。The way she behaved towards him was utterly ruthless. 她对待他真是无情至极。 Words are important, but the way a person stands, folds his or her arms or moves his or her hands can also give us information about his or her feelings. 言语固然重要,但人的站姿,抱臂的方式和手势也回告诉我们他(她)的情感。 2.作宾语 I hate the way she stared at me.我讨厌她盯我看的样子。 We like the way that her hair hangs down.我们喜欢她的头发笔直地垂下来。 You could tell she was foreign by the way she was dressed. 从她的穿著就可以看出她是外国人。 She could not hide her amusement at the way he was dancing. 她见他跳舞的姿势,忍俊不禁。 3.作表语 This is the way the accident happened.这就是事故如何发生的。 Believe it or not, that's the way it is. 信不信由你, 反正事情就是这样。 That's the way I look at it, too. 我也是这么想。 That was the way minority nationalities were treated in old China. 那就是少数民族在旧中

C++ #pragma code_seg用法

#pragma code_seg 格式如: #pragma code_seg( [ [ { push | pop}, ] [ identifier, ] ] [ "segment-name" [, "segment-class" ] ) 该指令用来指定函数在.obj文件中存放的节,观察OBJ文件可以使用VC自带的dumpbin命令行程序,函数在.obj文件中默认的存放节为.text节,如果code_seg 没有带参数的话,则函数存放在.text节中。 push (可选参数)将一个记录放到内部编译器的堆栈中,可选参数可以为一个标识符或者节名 pop(可选参数)将一个记录从堆栈顶端弹出,该记录可以为一个标识符或者节名identifier(可选参数)当使用push指令时,为压入堆栈的记录指派的一个标识符,当该标识符被删除的时候和其相关的堆栈中的记录将被弹出堆栈 "segment-name" (可选参数)表示函数存放的节名 例如: //默认情况下,函数被存放在.text节中 void func1() {// stored in .text } //将函数存放在.my_data1节中 #pragma code_seg(".my_data1") void func2() {// stored in my_data1 } //r1为标识符,将函数放入.my_data2节中 #pragma code_seg(push, r1, ".my_data2") void func3() {// stored in my_data2 } int main() { } 例如 #pragma code_seg(“PAGE”) 作用是将此部分代码放入分页内存中运行。 #pragma code_seg() 将代码段设置为默认的代码段 #pragma code_seg("INIT") 加载到INIT内存区域中,成功加载后,可以退出内存

(完整版)the的用法

定冠词the的用法: 定冠词the与指示代词this ,that同源,有“那(这)个”的意思,但较弱,可以和一个名词连用,来表示某个或某些特定的人或东西. (1)特指双方都明白的人或物 Take the medicine.把药吃了. (2)上文提到过的人或事 He bought a house.他买了幢房子. I've been to the house.我去过那幢房子. (3)指世界上独一无二的事物 the sun ,the sky ,the moon, the earth (4)单数名词连用表示一类事物 the dollar 美元 the fox 狐狸 或与形容词或分词连用,表示一类人 the rich 富人 the living 生者 (5)用在序数词和形容词最高级,及形容词等前面 Where do you live?你住在哪? I live on the second floor.我住在二楼. That's the very thing I've been looking for.那正是我要找的东西. (6)与复数名词连用,指整个群体 They are the teachers of this school.(指全体教师) They are teachers of this school.(指部分教师) (7)表示所有,相当于物主代词,用在表示身体部位的名词前 She caught me by the arm.她抓住了我的手臂. (8)用在某些有普通名词构成的国家名称,机关团体,阶级等专有名词前 the People's Republic of China 中华人民共和国 the United States 美国 (9)用在表示乐器的名词前 She plays the piano.她会弹钢琴. (10)用在姓氏的复数名词之前,表示一家人 the Greens 格林一家人(或格林夫妇) (11)用在惯用语中 in the day, in the morning... the day before yesterday, the next morning... in the sky... in the dark... in the end... on the whole, by the way...

Until的详细用法总结

Until的详细用法总结 你们知道until用法吗?我们一起来学习学习吧,下面就和大家分享,来欣赏一下吧。 Until的用法 比较until和till 此两个连词意义相同。肯定形式表示的意思是"做某事直至某时",动词必须是延续性的。否定形式表达的意思是"直至某时才做某事"。动词为延续性或非延续性都可以。正确使用这两个连词的关键之一就在于判断句中的动词该用肯定式还是否定式。 肯定句: I slept until midnight. 我一直睡到半夜时醒了。 Wait till I call you. 等着我叫你。 (在肯定句中可用before代替Lets get in the wheat before the sun sets.) 否定句: She didnt arrive until 6 oclock.

她直到6点才到。 until 用法上的三个难点 一、 1. until用在肯定句,谓语动词通常是延续性动词,如stand, stay, talk, wait等,表示主句动作终止的时间。如: ③I waited until he cam e back.我一直等到他回来。 ④The war lasted until 1945.战争持续到1945年。 如果用在否定句,谓语动词通常是瞬间性动词,如open, start, leave, arrive, finish, stop等,强调主句动作开始的时间。如: ⑤I didnt leave the boy until his mother turned up.直到这孩子的母亲来,我才离开。 ⑥The noise of the street didnt stop until it wa s midnight.街上的噪音直到半夜才停止。 2.连词until引导的从句中谓语动词的时态 1)until后面的从句中不能用一般将来时,应该用一般现在时代替。所谓的“主将从现”。 He will stay here until his mother comes back.

“the way+从句”结构的意义及用法

“theway+从句”结构的意义及用法 首先让我们来看下面这个句子: Read the followingpassageand talkabout it wi th your classmates.Try totell whatyou think of Tom and ofthe way the childrentreated him. 在这个句子中,the way是先行词,后面是省略了关系副词that或in which的定语从句。 下面我们将叙述“the way+从句”结构的用法。 1.the way之后,引导定语从句的关系词是that而不是how,因此,<<现代英语惯用法词典>>中所给出的下面两个句子是错误的:This is thewayhowithappened. This is the way how he always treats me. 2.在正式语体中,that可被in which所代替;在非正式语体中,that则往往省略。由此我们得到theway后接定语从句时的三种模式:1) the way+that-从句2)the way +in which-从句3) the way +从句 例如:The way(in which ,that) thesecomrade slookatproblems is wrong.这些同志看问题的方法

不对。 Theway(that ,in which)you’re doingit is comple tely crazy.你这么个干法,简直发疯。 Weadmired him for theway inwhich he facesdifficulties. Wallace and Darwingreed on the way inwhi ch different forms of life had begun.华莱士和达尔文对不同类型的生物是如何起源的持相同的观点。 This is the way(that) hedid it. I likedthe way(that) sheorganized the meeting. 3.theway(that)有时可以与how(作“如何”解)通用。例如: That’s the way(that) shespoke. = That’s how shespoke.

C++ #pragma预处理命令

#pragma预处理命令 #pragma可以说是C++中最复杂的预处理指令了,下面是最常用的几个#pragma 指令: #pragma comment(lib,"XXX.lib") 表示链接XXX.lib这个库,和在工程设置里写上XXX.lib的效果一样。 #pragma comment(linker,"/ENTRY:main_function") 表示指定链接器选项/ENTRY:main_function #pragma once 表示这个文件只被包含一次 #pragma warning(disable:4705) 表示屏蔽警告4705 C和C++程序的每次执行都支持其所在的主机或操作系统所具有的一些独特的特点。例如,有些程序需要精确控制数据存放的内存区域或控制某个函数接收的参数。#pragma为编译器提供了一种在不同机器和操作系统上编译以保持C和C++完全兼容的方法。#pragma是由机器和相关的操作系统定义的,通常对每个编译器来说是不同的。 如果编译器遇到不认识的pragma指令,将给出警告信息,然后继续编译。Microsoft C and C++ 的编译器可识别以下指令:alloc_text,auto_inline,bss_seg,check_stack,code_seg,comment,component,conform,const_seg,data_seg,deprecated,fenv_access,float_control,fp_contract,function,hdrstop,include_alias,init_seg,inline_depth,inline_recursion,intrinsic,make_public,managed,message,omp,once,optimize,pack,pointers_to_members,pop_macro,push_macro,region, endregion,runtime_checks,section,setlocale,strict_gs_check,unmanaged,vtordisp,warning。其中conform,init_seg, pointers_to_members,vtordisp仅被C++编译器支持。 以下是常用的pragma指令的详细解释。 1.#pragma once。保证所在文件只会被包含一次,它是基于磁盘文件的,而#ifndef 则是基于宏的。

not until的北京中考用法

【中考链接】 1.Not until 1. 托尼经过和老师长时间地反复讨论之后,才下定决心尝试这个新想法。(09西城一模) Tony didn’t ________________________ discussing it with his teacher again and again. 2. 这本小说太长了,我直到昨天才读完。(09丰台二模) The novel was so long _________________________________________ until yesterday. 3. 昨天晚上比尔直到十二点钟才上床睡觉。(09顺义二模) Bill _____________________________ 12 o’clock last night. 4. 昨天下午我直到写完作业才回家。(09石景山模拟) I __________ go home yesterday afternoon ______________ I finished my homework. 5.刘先生过去总抽烟。知道病得严重了,他才戒烟。(11延庆二模) Mr Liu used to smoke a lot.______________ he was seriously ill. 6. 昨天李英洗完衣服才做作业。(11房山一模) Li Ying ________________ her clothes yesterday. 主将从现 1.Be confident! Everyone will succeed if he ___________ in himself. (11 海淀一模) A.believe B. believes C.believed D.will believe 2.You won't have the chance to succeed when you ____________.(11 海淀二模) A.gave up B.give up C. will give up D.are giving up 3.----What will you do tomorrow? (11 西城二模) ----- I will go out for fun if it ___________ fine. A.is B.be C. will be D. Was 4.We ____________ for Dalian as soon as we get the train tickets.(11 东城一模) A.leave B. left C.will leave D.were leaving 4.George will send us an e-mail as soon as he ________in London.(11 东城二模) A.work B.working C. worked D. To work 6.Difficult work___________ easy if you do it very carefully.(11朝阳一模) A.become B.became C.will become D.has become 2.Make 的用法 1.Let's ____________ goodbye to plastic bags in order to protect the environment .(11海淀一模) A. say B. said C. saying D. to say 2.Sarah always makes her son ___________ his hands before eating. (11海淀二模) A.wash B. washed C.washing D.to wash 3.My mother made me ___________ the piano when I was very young . Now, I begin to understand her. (11西城一模) A.play B. to play C. playing D. play 4.----Don't always make Tony ________ this or that. He is already a big boy.(11朝阳一模) ----Maybe you're right. A.do B.done C. to do D.doing 5.让我们忘记分歧,做好朋友吧。(11海淀二模) ____________ forget our differences and be good friends. 6.今天下午没课。让我们去公园吧!(11东城二模) We're free this afternoon.__________ go to the park.

way 用法

表示“方式”、“方法”,注意以下用法: 1.表示用某种方法或按某种方式,通常用介词in(此介词有时可省略)。如: Do it (in) your own way. 按你自己的方法做吧。 Please do not talk (in) that way. 请不要那样说。 2.表示做某事的方式或方法,其后可接不定式或of doing sth。 如: It’s the best way of studying [to study] English. 这是学习英语的最好方法。 There are different ways to do [of doing] it. 做这事有不同的办法。 3.其后通常可直接跟一个定语从句(不用任何引导词),也可跟由that 或in which 引导的定语从句,但是其后的从句不能由how 来引导。如: 我不喜欢他说话的态度。 正:I don’t like the way he spoke. 正:I don’t like the way that he spoke. 正:I don’t like the way in which he spoke. 误:I don’t like the way how he spoke. 4.注意以下各句the way 的用法: That’s the way (=how) he spoke. 那就是他说话的方式。 Nobody else loves you the way(=as) I do. 没有人像我这样爱你。 The way (=According as) you are studying now, you won’tmake much progress. 根据你现在学习情况来看,你不会有多大的进步。 2007年陕西省高考英语中有这样一道单项填空题: ——I think he is taking an active part insocial work. ——I agree with you_____. A、in a way B、on the way C、by the way D、in the way 此题答案选A。要想弄清为什么选A,而不选其他几项,则要弄清选项中含way的四个短语的不同意义和用法,下面我们就对此作一归纳和小结。 一、in a way的用法 表示:在一定程度上,从某方面说。如: In a way he was right.在某种程度上他是对的。注:in a way也可说成in one way。 二、on the way的用法 1、表示:即将来(去),就要来(去)。如: Spring is on the way.春天快到了。 I'd better be on my way soon.我最好还是快点儿走。 Radio forecasts said a sixth-grade wind was on the way.无线电预报说将有六级大风。 2、表示:在路上,在行进中。如: He stopped for breakfast on the way.他中途停下吃早点。 We had some good laughs on the way.我们在路上好好笑了一阵子。 3、表示:(婴儿)尚未出生。如: She has two children with another one on the way.她有两个孩子,现在还怀着一个。 She's got five children,and another one is on the way.她已经有5个孩子了,另一个又快生了。 三、by the way的用法

#pragma data code ICCAVR的使用

#pragma data:code 在Keil中为了节省数据存储器的空间,通过“code”关键字来定义一个数组或字符串将被存储在程序存储器中: uchar code buffer[]={0,1,2,3,4,5}; uchar code string[]="Armoric" ; 而这类代码移值到ICCAVR上时是不能编译通过的。我们可以通过"const" 限定词来实现对存储器的分配: #pragma data:code const unsigned char buffer[]={0,1,2,3,4,5}; const unsigned char string[]="Armoric"; #pragma data:data 注意: 《1》使用ICCAVR6.31时,#pragma data :code ;#pragma data:data ; 这些语法时在"data:cod"、"data:data"字符串中间不能加空格,否则编译不能通过。 《2》const 在ICCAVR是一个扩展关键词,它与ANSIC标准有冲突,移值到其它的编译器使用时也需要修改相关的地方。 在ICCAVR中对数组和字符串的五种不同空间分配: const unsigned char buffer[]={0,1,2,3,4,5}; //buffer数组被分配在程序存储区中 const unsigned char string[]="Armoric" ; //stringp字符串被分配在程序存储区中 const unsigned char *pt //指针变量pt被分配在数据存储区中,指向程序存储区中的字符类型数据 unsigned char *const pt //指针变量pt被分配在程序存储区中,指向数据存储区中的字符类型数据 const unsigned char *const pt //指针变量pt被分配在程序存储区,指向程序存储区中的字符类型数据 unsigned char *pt //指针变量pt被分配在数据存储区中,指向数据存储区中的数据 请问#pragma data:code和#pragma data:data是什么意思? 前者表示:随后的数据将存贮在程序区,即FLASH区,此区只能存贮常量,比如表格之类。

标点符号用法分析

标点符号用法 一、标点符号 标点符号:辅助文字记录语言的符号,是书面语的有机组成部分,用来表示语句的停顿、语气以及标示某些成分(主要是词语)的特定性质和作用。 句子:前后都有较大停顿、带有一定的语气和语调、表达相对完整意义的语言单位。 复句:由两个或多个在意义上有密切关系的分句组成的语言单位,包括简单复句(内部只有一层语义关系)和多重复句(内部包含多层语义关系)。 分句:复句内两个或多个前后有停顿、表达相对完整意义、不带有句末语气和语调、有的前面可添加关联词语的语言单位。 陈述句:用来说明事实的句子。 祈使句:用来要求听话人做某件事情的句子。 疑问句:用来提出问题的句子。 感叹句:用来抒发某种强烈感情的句子。 词语:词和短语(词组)。词,即最小的能独立运用的语言单位。短语,即由两个或两个以上的词按一定的语法规则组成的表达一定意义的语言单位,也叫词组。 二、分类 标点符号分为点号和标号两大类。

点号的作用是点断,主要表示说话时的停顿和语气。点号又分为句末点号和句内点号。 句末点号用在句末,表示句末停顿和句子的语气,包括句号、问号、叹号。 句内点号用在句内,表示句内各种不同性质的停顿,有逗号、顿号、分号、冒号。 标号的作用是标明,主要标示某些成分(主要是词语)的特定性质和作用。包括引号、括号、破折号、省略号、着重号、连接号、间隔号、书名号、专名号、分隔号。 (一)句号 1.用于句子末尾,表示陈述语气。使用句号主要根据语段前后有较大停顿、带有陈述语气和语调,并不取决于句子的长短。 2.有时也可表示较缓和的祈使语气和感叹语气。 请您稍等一下。 我不由地感到,这些普通劳动者也是同样值得尊敬的。 (二)问号 主要表示句子的疑问语气。形式是“?”。 1.用于句子末尾,表示疑问语气(包括反问、设问等疑问类型)。使用问号主要根据语段前后有较大停顿、带有疑问语气和语调,并不取决于句子的长短。 2.选择问句中,通常只在最后一个选项的末尾用问号,各个选项之间一般用逗号隔开。当选项较短且选项之间几乎没有停顿时,选项之间可不用逗号。当选项较多或较长,或有意突出每个选项的独立性时,也可每个选项之后都用问号。 3.问号也有标号的用法,即用于句内,表示存疑或不详。 马致远(1250?―1321)。 使用问号应以句子表示疑问语气为依据,而并不根据句子中包含有疑问词。当含有疑问词的语段充当某种句子成分,而句子并不表示疑问语气时,句末不用问号。

until用法归纳

使用注意事项: ◇注意事项一 until用于肯定句中,表示主句的动作一直持续到从句动作发生或状态出现时为止。一般可译为“……直到……为止”。在这种用法中,主句的谓语动词必须是持续动词(非瞬间动词),如live, wait , last, love, like, stay, work, continue 等。 until用于否定句中,表示主句的动作在从句的动作发生之前尚未发生,或者说主句的动作在从句的动作发生之后才开始。一般可译为“直到……才”。 ◇注意事项二 until后面的从句中不能用一般将来时,应该用一般现在时代替。所谓的“主将从现”。 He will stay here until his mother comes back. They will study at the school until their parents come to take them home. ◇注意事项三(该考点为高中内容) till和until的意思基本相同,用法也基本一样,但until语气较重,多用于较正式的文体里。till多用于英式英语,until多用于美式英语;till不能用在句首,也不能用在not开头的短语或从句里,而until可以。在这种情况下应用倒装语序。 Until he came home, we knew the news. 在他到家之前,我们不知道这消息。Not until nine o’clock yesterday evening did we fi nish the work. 直到昨晚九点,我们才完成这项工作。 ◇注意事项四(该考点在初中阶段基本不涉及)

pragma的用法

#pragma的用法 在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义, 编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。 其格式一般为: #pragma para。其中para为参数,下面来看一些常用的参数。 1)message 参数 message参数是我最喜欢的一个参数,它能够在编译信息输出窗口中输出相应的信息,这对于源代码信息的控制是非常重要的。其使用方法为: #pragma message("消息文本") 当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。 当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有 没有正确的设置这些宏, 此时我们可以用这条指令在编译的时候就进行检查。假设我们希望判断自己有没有在源代码的什么地方定义了_X86这个宏, 可以用下面的方法: #ifdef _X86 #pragma message("_X86 macro activated!") #endif 我们定义了_X86这个宏以后,应用程序在编译时就会在编译输出窗口里显示"_86 macro activated!"。 我们就不会因为不记得自己定义的一些特定的宏而抓耳挠腮了。 (2)另一个使用得比较多的pragma参数是code_seg 格式如: #pragma code_seg( ["section-name" [, "section-class"] ] ) 它能够设置程序中函数代码存放的代码段,当我们开发驱动程序的时候就会使用到 它。 (3)#pragma once (比较常用) 只要在头文件的最开始加入这条指令就能够保证头文件被编译一次,这条指令实际上 在VC6中就已经有了, 但是考虑到兼容性并没有太多的使用它。 (4)#pragma hdrstop 表示预编译头文件到此为止,后面的头文件不进行预编译。BCB可以预编译头文件以 加快链接的速度, 但如果所有头文件都进行预编译又可能占太多磁盘空间,所以使用这个选项排除一些头文

定语从句用法分析

定语从句用法分析 定语从句在整个句子中担任定语,修饰一个名词或代词,被修饰的名词或代词叫先行词。定语从句通常出现在先行词之后,由关系词(关系代词或关系副词)引出。 eg. The boys who are planting trees on the hill are middle school students 先行词定语从句 #1 关系词: 关系代词:who, whom, whose, that, which, as (句子中缺主要成份:主语、宾语、定语、表语、同位语、补语), 关系副词:when, where, why (句子中缺次要成份:状语)。 #2 关系代词引导的定语从句 关系代词引导定语从句,代替先行词,并在句中充当主语、宾语、定语等主要成分。 1)who, whom, that 指代人,在从句中作主语、宾语。 eg. Is he the man who/that wants to see you?(who/that在从句中作主语) ^ He is the man who/whom/ that I saw yesterday.(who/whom/that在从句中作宾语) ^ 2)whose 用来指人或物,(只用作定语, 若指物,它还可以同of which互换)。eg. They rushed over to help the man whose car had broken down. Please pass me the book whose cover is green. = the cover of which/of which the cover is green. 3)which, that指代物,在从句中可作主语、宾语。 eg. The package (which / that)you are carrying is about to come unwrapped. ^ (which / that在从句中作宾语,可省略) 关系代词在定语从句中作主语时,从句谓语动词的人称和数要和先行词保持一致。 eg. Is he the man who want s to see you? #3.关系副词引导的定语从句 关系副词when, where, why引导定语从句,代替先行词(时间、地点或理由),并在从句中作状语。 eg. Two years ago, I was taken to the village where I was born. Do you know the day when they arrived? The reason why he refused is that he was too busy. 注意: 1)关系副词常常和"介词+ which"结构互换 eg. There are occasions when (on which)one must yield (屈服). Beijing is the place where(in which)I was born. Is this the reason why (for which)he refused our offer? * 2)在非正式文体中,that代替关系副词或"介词+ which",放在时间、地点、理由的名词,在口语中that常被省略。 eg. His father died the year (that / when / in which)he was born. He is unlikely to find the place (that / where / in which)he lived forty years ago.

The way的用法及其含义(一)

The way的用法及其含义(一) 有这样一个句子:In 1770 the room was completed the way she wanted. 1770年,这间琥珀屋按照她的要求完成了。 the way在句中的语法作用是什么?其意义如何?在阅读时,学生经常会碰到一些含有the way 的句子,如:No one knows the way he invented the machine. He did not do the experiment the way his teacher told him.等等。他们对the way 的用法和含义比较模糊。在这几个句子中,the way之后的部分都是定语从句。第一句的意思是,“没人知道他是怎样发明这台机器的。”the way的意思相当于how;第二句的意思是,“他没有按照老师说的那样做实验。”the way 的意思相当于as。在In 1770 the room was completed the way she wanted.这句话中,the way也是as的含义。随着现代英语的发展,the way的用法已越来越普遍了。下面,我们从the way的语法作用和意义等方面做一考查和分析: 一、the way作先行词,后接定语从句 以下3种表达都是正确的。例如:“我喜欢她笑的样子。” 1. the way+ in which +从句 I like the way in which she smiles. 2. the way+ that +从句 I like the way that she smiles. 3. the way + 从句(省略了in which或that) I like the way she smiles. 又如:“火灾如何发生的,有好几种说法。” 1. There were several theories about the way in which the fire started. 2. There were several theories about the way that the fire started.

stm32中使用#pragma pack(非常有用的字节对齐用法说明)

#pragma pack(4) //按4字节对齐,但实际上由于结构体中单个成员的最大占用字节数为2字节,因此实际还是按2字节对齐 typedef struct { char buf[3];//buf[1]按1字节对齐,buf[2]按1字节对齐,由于buf[3]的下一成员word a是按两字节对齐,因此buf[3]按1字节对齐后,后面只需补一空字节 word a; //#pragma pack(4),取小值为2,按2字节对齐。 }kk; #pragma pack() //取消自定义字节对齐方式 对齐的原则是min(sizeof(word ),4)=2,因此是2字节对齐,而不是我们认为的4字节对齐。 这里有三点很重要: 1.每个成员分别按自己的方式对齐,并能最小化长度 2.复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度 3.对齐后的结构体整体长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐 补充一下,对于数组,比如: char a[3];这种,它的对齐方式和分别写3个char是一样的.也就是说它还是按1个字节对齐. 如果写: typedef char Array3[3]; Array3这种类型的对齐方式还是按1个字节对齐,而不是按它的长度. 不论类型是什么,对齐的边界一定是1,2,4,8,16,32,64....中的一个. 声明: 整理自网络达人们的帖子,部分参照MSDN。 作用: 指定结构体、联合以及类成员的packing alignment; 语法: #pragma pack( [show] | [push | pop] [, identifier], n ) 说明: 1,pack提供数据声明级别的控制,对定义不起作用; 2,调用pack时不指定参数,n将被设成默认值; 3,一旦改变数据类型的alignment,直接效果就是占用memory的减少,但是performance会下降; 语法具体分析: 1,show:可选参数;显示当前packing aligment的字节数,以warning message的形式被显示; 2,push:可选参数;将当前指定的packing alignment数值进行压栈操作,这里的栈是the internal compiler stack,同时设置当前的packing alignment为n;如果n没有指定,则将当前的packing alignment数值压栈; 3,pop:可选参数;从internal compiler stack中删除最顶端的record;如果没有指定n,则当前栈顶record即为新的packing alignment 数值;如果指定了n,则n将成为新的packing aligment数值;如果指定了identifier,则internal compiler stack中的record都将被pop 直到identifier被找到,然后pop出identitier,同时设置packing alignment数值为当前栈顶的record;如果指定的identifier并不存在于internal compiler stack,则pop操作被忽略; 4,identifier:可选参数;当同push一起使用时,赋予当前被压入栈中的record一个名称;当同pop一起使用时,从internal compiler stack 中pop出所有的record直到identifier被pop出,如果identifier没有被找到,则忽略pop操作; 5,n:可选参数;指定packing的数值,以字节为单位;缺省数值是8,合法的数值分别是1、2、4、8、16。 重要规则: 1,复杂类型中各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个类型的地址相同; 2,每个成员分别对齐,即每个成员按自己的方式对齐,并最小化长度;规则就是每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数中较小的一个对齐; 3,结构体、联合体或者类的数据成员,第一个放在偏移为0的地方;以后每个数据成员的对齐,按照#pragma pack指定的数值和这个数据成员自身长度两个中比较小的那个进行;也就是说,当#pragma pack指定的值等于或者超过所有数据成员长度的时候,这个指定值的大小将不产生任何效果; 4,复杂类型(如结构体)整体的对齐是按照结构体中长度最大的数据成员和#pragma pack指定值之间较小的那个值进行;这样当数据成员为复杂类型(如结构体)时,可以最小化长度; 5,复杂类型(如结构体)整体长度的计算必须取所用过的所有对齐参数的整数倍,不够补空字节;也就是取所用过的所有对齐参数中最大的那个值的整数倍,因为对齐参数都是2的n次方;这样在处理数组时可以保证每一项都边界对齐; 对齐的算法:由于各个平台和编译器的不同,现以本人使用的gcc version 3.2.2编译器(32位x86平台)为例子,来讨论编译器对struct 数据结构中的各成员如何进行对齐的。 在相同的对齐方式下,结构体内部数据定义的顺序不同,结构体整体占据内存空间也不同,如下: 设结构体如下定义: struct A { int a; //a的自身对齐值为4,偏移地址为0x00~0x03,a的起始地址0x00满足0x00%4=0;

相关文档
最新文档