C语言中表达式和表达式语句的区别(共6篇)由网友“benny”投稿提供,这里给大家推荐分享一些C语言中表达式和表达式语句的区别,供大家参考。
篇1:C语言中表达式和表达式语句的区别
表达式:
表达式是操作符、操作数和标点符号组成的序列,其目的是用来说明…个计算过程,
表达式可以嵌套,例如:2+3+(5*sizeof(int))/345。
表达式根据某些约定、求值次序、结合和优先级规则来进行计算。
所谓约定,即类型转换的约定。例如:
float a;
a=5/2;
结果。得到值为2。5/2是整数除法取整, 因为5和2都是整数,不会由于a是float型而轻易改变运算的性质,
所谓求值次序,是指表达式中各个操作数的求值次序视编译器不同而不同。见3.9节。
所谓结合性,是指表达式中出现同等优先级的操作符时,该先做哪个操作的规定。例如:
d=a+b-c; //C++规定,加减法先左后右,先做a+b,其结果再减去c
d=a=3; //C++规定,等号是先右后左。先做a=3,其结果再赋给d
所谓优先级,是指不同优先级的操作符,总是先做优先级高的操作。例如:
d=a+b*c; //乘法优先级比加法高。先做b*c,其结果再与a相加
表达式语句:
C++中所有的操作运算都通过表达式来实现。 由表达式组成的语句称为表达式语句。
它由一个表达式后接一个分号“;”组成。
篇2:C语言初学者入门讲座4运算符和表达式
运算符的种类、优先级和结合性
C语言中运算符和表达式数量之多, 在高级语言中是少见的,正是丰富的运算符和表达式使C语言功能十分完善。 这也是C语言的主要特点之一。
C语言的运算符不仅具有不同的优先级, 而且还有一个特点,就是它的结合性。在表达式中, 各运算量参与运算的先后顺序不仅要遵守运算符优先级别的规定,还要受运算符结合性的制约, 以便确定是自左向右进行运算还是自右向左进行运算。 这种结合性是其它高级语言的运算符所没有的,因此也增加了C语言的复杂性。
运算符的种类C语言的运算符可分为以下几类:
1.算术运算符
用于各类数值运算。包括加(+)、减(-)、乘(*)、除(/)、求余(或称模运算,%)、自增(++)、自减(--)共七种。
2.关系运算符
用于比较运算。包括大于(>)、小于(<)、等于(==)、大于等于(>=)、小于等于(<=)和不等于(!=)六种。
3.逻辑运算符
用于逻辑运算。包括与(&&)、或(||)、非(!)三种。
4.位操作运算符
参与运算的量,按二进制位进行运算。包括位与(&)、位或(|)、位非(~)、位异或(^)、左移(<<)、右移(>>)六种。
5.赋值运算符
用于赋值运算,分为简单赋值(=)、复合算术赋值(+=,-=,*=,/=,%=)和复合位运算赋值(&=,|=,^=,>>=,<<=)三类共十一种。
6.条件运算符
这是一个三目运算符,用于条件求值(?:)。
7.逗号运算符
用于把若干表达式组合成一个表达式(,)。
8.指针运算符
用于取内容(*)和取地址(&)二种运算。
9.求字节数运算符
用于计算数据类型所占的字节数(sizeof)。
10.特殊运算符
有括号,下标[],成员(→,.)等几种。
优先级和结合性
C语言中,运算符的运算优先级共分为15级。1级最高,15级最低。在表达式中,优先级较高的先于优先级较低的进行运算。 而在一个运算量两侧的运算符优先级相同时, 则按运算符的结合性所规定的结合方向处理。 C语言中各运算符的结合性分为两种,即左结合性(自左至右)和右结合性(自右至左)。例如算术运算符的结合性是自左至右,即先左后右。如有表达式x-y+z则y应先与“-”号结合, 执行x-y运算,然后再执行+z的运算。这种自左至右的结合方向就称为“左结合性”。而自右至左的结合方向称为“右结合性”。 最典型的右结合性运算符是赋值运算符。如x=y=z,由于“=”的右结合性,应先执行y=z再执行x=(y=z)运算。 C语言运算符中有不少为右结合性,应注意区别,以避免理解错误。
算术运算符和算术表达式基本的算术运算符
1.加法运算符“+”加法运算符为双目运算符,即应有两个量参与加法运算。如a+b,4+8等。具有右结合性。
2.减法运算符“-”减法运算符为双目运算符。但“-”也可作负值运算符,此时为单目运算,如-x,-5等具有左结合性。
3.乘法运算符“*”双目运算,具有左结合性。
4.除法运算符“/”双目运算具有左结合性。参与运算量均为整型时, 结果也为整型,舍去小数。如果运算量中有一个是实型,则结果为双精度实型。
void main(){
printf(“\n\n%d,%d\n”,20/7,-20/7);
printf(“%f,%f\n”,20.0/7,-20.0/7);
}
双目运算具有左结合性。参与运算量均为整型时, 结果也为整型,舍去小数。如果运算量中有一个是实型,则结果为双精度实型。 printf(“\n\n%d,%d\n”,20/7,-20/7);
printf(“%f,%f\n”,20.0/7,-20.0/7);
本例中,20/7,-20/7的结果均为整型,小数全部舍去。而20.0/7和-20.0/7由于有实数参与运算,因此结果也为实型。
5.求余运算符(模运算符)“%”双目运算,具有左结合性。要求参与运算的量均为整型。 求余运算的结果等于两数相除后的余数。
void main(){
printf(“%d\n”,100%3);
}
双目运算,具有左结合性。求余运算符% 要求参与运算的量均为整型。本例输出100除以3所得的余数1。
自增1,自减1运算符
自增1运算符记为“++”,其功能是使变量的值自增1。自减1运算符记为“--”,其功能是使变量值自减1。自增1,自减1运算符均为单目运算,都具有右结合性。可有以下几种形式: ++i i自增1后再参与其它运算。--i i自减1后再参与其它运算。
i++ i参与运算后,i的值再自增1。
i-- i参与运算后,i的值再自减1。
在理解和使用上容易出错的是i++和i--。 特别是当它们出在较复杂的表达式或语句中时,常常难于弄清,因此应仔细分析。
void main(){
int i=8;
printf(“%d\n”,++i);
printf(“%d\n”,--i);
printf(“%d\n”,i++);
printf(“%d\n”,i--);
printf(“%d\n”,-i++);
printf(“%d\n”,-i--);
} i<--8
i<--i+1
i<--i-1
i<--i+1
i<--i-1
i<--i+1
i<--i-1 int i=8;
printf(“%d\n”,++i);
printf(“%d\n”,--i);
printf(“%d\n”,i++);
printf(“%d\n”,i--);
printf(“%d\n”,-i++);
printf(“%d\n”,-i--);
i的初值为8
第2行i加1后输出故为9;
第3行减1后输出故为8;
第4行输出i为8之后再加1(为9);
第5行输出i为9之后再减1(为8) ;
第6行输出-8之后再加1(为9);
第7行输出-9之后再减1(为8)
void main(){
int i=5,j=5,p,q;
p=(i++)+(i++)+(i++);
q=(++j)+(++j)+(++j);
printf(“%d,%d,%d,%d”,p,q,i,j);
}
i<--5,j<--5,p<--0,q<--0
i+i+i--->p,i+1-->i,i+1-->i,i+1-->i
j+1->j,j+1->j,j+1->j,j+j+j->q int i=5,j=5,p,q;
p=(i++)+(i++)+(i++);
q=(++j)+(++j)+(++j);
这个程序中,对P=(i++)+(i++)+(i++)应理解为三个i相加,故P值为15,
然后i再自增1三次相当于加3故i的最后值为8。而对于q 的值则不然,q=(++j)+(++j)+(++j)应理解为q先自增1,再参与运算,由于q自增1三次后值为8,三个8相加的和为24,j的最后值仍为8。算术表达式表达式是由常量、变量、函数和运算符组合起来的式子。 一个表达式有一个值及其类型, 它们等于计算表达式所得结果的值和类型。表达式求值按运算符的优先级和结合性规定的顺序进行。 单个的常量、变量、函数可以看作是表达式的特例。
算术表达式
是由算术运算符和括号连接起来的式子, 以下是算术表达式的例子:
a+b (a*2)/c (x+r)*8-(a+b)/7 ++i sin(x)+sin(y) (++i)-(j++)+(k--)
赋值运算符和赋值表达式
简单赋值运算符和表达式,简单赋值运算符记为“=”。由“= ”连接的式子称为赋值表达式。其一般形式为: 变量=表达式 例如:
x=a+b
w=sin(a)+sin(b)
y=i+++--j 赋值表达式的功能是计算表达式的值再赋予左边的变量。赋值运算符具有右结合性。因此
a=b=c=5
可理解为
a=(b=(c=5))
在其它高级语言中,赋值构成了一个语句,称为赋值语句。 而在C中,把“=”定义为运算符,从而组成赋值表达式。 凡是表达式可以出现的地方均可出现赋值表达式。例如,式子x=(a=5)+(b=8)是合法的。它的意义是把5赋予a,8赋予b,再把a,b相加,和赋予x ,故x应等于13。
在C语言中也可以组成赋值语句,按照C语言规定, 任何表达式在其未尾加上分号就构成为语句。因此如x=8;a=b=c=5;都是赋值语句,在前面各例中我们已大量使用过了。
如果赋值运算符两边的数据类型不相同, 系统将自动进行类型转换,即把赋值号右边的类型换成左边的类型。具体规定如下:
1.实型赋予整型,舍去小数部分。前面的例2.9已经说明了这种情况。
2.整型赋予实型,数值不变,但将以浮点形式存放, 即增加小数部分(小数部分的值为0)。
3.字符型赋予整型,由于字符型为一个字节, 而整型为二个字节,故将字符的ASCII码值放到整型量的低八位中,高八位为0。
4.整型赋予字符型,只把低八位赋予字符量。
void main(){
int a,b=322;
float x,y=8.88;
char c1='k',c2;
a=y;
x=b;
a=c1;
c2=b;
printf(“%d,%f,%d,%c”,a,x,a,c2);
}
int a,b=322;
float x,y=8.88;
char c1='k',c2;
printf(“%d,%f,%d,%c”,a=y,x=b,a=c1,c2=b);
本例表明了上述赋值运算中类型转换的规则。a为整型,赋予实型量y值888后只取整数8。x为实型,赋予整型量b值322, 后增加了小数部分。字符型量c1赋予a变为整型,整型量b赋予c2 后取其低八位成为字符型(b的低八位为01000010,即十进制66,按ASCII码对应于字符B)。
复合赋值符及表达式
在赋值符“=”之前加上其它二目运算符可构成复合赋值符。如
+=,-=,*=,/=,%=,<<=,>>=,&=,^=,|=。 构成复合赋值表达式的一般形式为: 变量 双目运算符=表达式 它等效于 变量=变量 运算符 表达式 例如: a+=5 等价于a=a+5 x*=y+7 等价于x=x*(y+7) r%=p 等价于r=r%p 复合赋值符这种写法,对初学者可能不习惯, 但十分有利于编译处理,能提高编译效率并产生质量较高的目标代码。逗号运算符和逗号表达式在
逗号运算符
C语言中逗号“,”也是一种运算符,称为逗号运算符。 其功能是把两个表达式连接起来组成一个表达式, 称为逗号表达式。
其一般形式为: 表达式1,表达式2 其求值过程是分别求两个表达式的值,并以表达式2的值作为整个逗号表达式的值。
void main(){
int a=2,b=4,c=6,x,y;
y=(x=a+b),(b+c);
printf(“y=%d,x=%d”,y,x);
}
a<--2,b<--4,c<--6,x<--0,y<--0
x<--a+b,y<---b+c
本例中,y等于整个逗号表达式的值,也就是表达式2的值,x是第一个表达式的值。对于逗号表达式还要说明两点:
1.逗号表达式一般形式中的表达式1和表达式2 也可以又是逗号表达式。例如: 表达式1,(表达式2,表达式3) 形成了嵌套情形。因此可以把逗号表达式扩展为以下形式: 表达式1,表达式2,…表达式n 整个逗号表达式的值等于表达式n的值。
2.程序中使用逗号表达式,通常是要分别求逗号表达式内各表达式的值,并不一定要求整个逗号表达式的值。
3.并不是在所有出现逗号的地方都组成逗号表达式,如在变量说明中,函数参数表中逗号只是用作各变量之间的间隔符。
篇3:C++/C编程第4章表达式和基本语句
可能怀疑:连if、for、while、goto、switch这样简单的东西也要探讨编程风格,是不是小题大做?
我真的发觉很多程序员用隐含错误的方式写表达式和基本语句,我自己也犯过类似的错误,
表达式和语句都属于C++/C的短语结构语法。它们看似简单,但使用时隐患比较多。
本章归纳了正确使用表达式和语句的一些规则与建议。
4.1 运算符的优先级
C++/C语言的运算符有数十个,运算符的优先级与结合律如表4-1所示。注意一元运算符 + - * 的优先级高于对应的二元运算符。
优先级
运算符
结合律
从
高
到
低
排
列
( ) [ ] -> .
从左至右
! ~ ++ -- (类型)sizeof
+ - * &
从右至左
* / %
从左至右
+ -
从左至右
<< >>
从左至右
<<= > >=
从左至右
== !=
从左至右
&
从左至右
^
从左至右
|
从左至右
&&
从左至右
||
从右至左
?:
从右至左
= += -= *= /= %= &= ^=
|= <<= >>=
从左至右
表4-1运算符的优先级与结合律
l【规则4-1-1】如果代码行中的运算符比较多,用括号确定表达式的操作顺序,避免使用默认的优先级。
由于将表4-1熟记是比较困难的,为了防止产生歧义并提高可读性,应当用括号确定表达式的操作顺序。例如:
word = (high << 8) | low
if ((a | b) && (a & c))
4.2复合表达式
如 a = b = c = 0这样的表达式称为复合表达式。允许复合表达式存在的理由是:(1)书写简洁;(2)可以提高编译效率。但要防止滥用复合表达式。
l【规则4-2-1】不要编写太复杂的复合表达式。
例如:
i = a >= b && c < d && c + f <= g + h ;//复合表达式过于复杂
l【规则4-2-2】不要有多用途的复合表达式。
例如:
d = (a = b + c) + r ;
该表达式既求a值又求d值。应该拆分为两个独立的语句:
a = b + c;
d = a + r;
l【规则4-2-3】不要把程序中的复合表达式与“真正的数学表达式”混淆。
例如:
if (a < b < c)// a < b < c是数学表达式而不是程序表达式
并不表示
if ((a
而是成了令人费解的
if ( (a 4.3if语句 if语句是C++/C语言中最简单、最常用的语句,然而很多程序员用隐含错误的方式写if语句。本节以“与零值比较”为例,展开讨论。 4.3.1 布尔变量与零值比较 l【规则4-3-1】不可将布尔变量直接与TRUE、FALSE或者1、0进行比较。 根据布尔类型的语义,零值为“假”(记为FALSE),任何非零值都是“真”(记为TRUE)。TRUE的值究竟是什么并没有统一的标准。例如Visual C++ 将TRUE定义为1,而Visual Basic则将TRUE定义为-1。 假设布尔变量名字为flag,它与零值比较的标准if语句如下: if (flag)// 表示flag为真 if (!flag)// 表示flag为假 其它的用法都属于不良风格,例如: if (flag == TRUE) if (flag == 1 ) if (flag == FALSE) if (flag == 0) 4.3.2 整型变量与零值比较 l【规则4-3-2】应当将整型变量用“==”或“!=”直接与0比较。 假设整型变量的名字为value,它与零值比较的标准if语句如下: if (value == 0) if (value != 0) 不可模仿布尔变量的风格而写成 if (value)// 会让人误解 value是布尔变量 if (!value) 4.3.3 浮点变量与零值比较 l【规则4-3-3】不可将浮点变量用“==”或“!=”与任何数字比较。 千万要留意,无论是float还是double类型的变量,都有精度限制。所以一定要避免将浮点变量用“==”或“!=”与数字比较,应该设法转化成“>=”或“<=”形式。 假设浮点变量的名字为x,应当将 if (x == 0.0)// 隐含错误的比较 转化为 if ((x>=-EPSINON) && (x<=EPSINON)) 其中EPSINON是允许的误差(即精度)。 4.3.4 指针变量与零值比较 l【规则4-3-4】应当将指针变量用“==”或“!=”与NULL比较。 指针变量的零值是“空”(记为NULL)。尽管NULL的值与0相同,但是两者意义不同。假设指针变量的名字为p,它与零值比较的标准if语句如下: if (p == NULL) // p与NULL显式比较,强调p是指针变量 if (p != NULL) 不要写成 if (p == 0) // 容易让人误解p是整型变量 if (p != 0) 或者 if (p)// 容易让人误解p是布尔变量 if (!p) 4.3.5对if语句的补充说明 有时候我们可能会看到if (NULL == p) 这样古怪的格式, 不是程序写错了,是程序员为了防止将 if (p == NULL) 误写成 if (p = NULL),而有意把p和NULL颠倒。编译器认为 if (p = NULL) 是合法的,但是会指出 if (NULL = p)是错误的,因为NULL不能被赋值。 程序中有时会遇到if/else/return的组合,应该将如下不良风格的程序 if (condition) return x; return y; 改写为 if (condition) { return x; } else { return y; } 或者改写成更加简练的 return (condition ? x : y); 4.4循环语句的效率 C++/C循环语句中,for语句使用频率最高,while语句其次,do语句很少用。本节重点论述循环体的效率。提高循环体效率的基本办法是降低循环体的复杂性。 l【建议4-4-1】在多重循环中,如果有可能,应当将最长的循环放在最内层,最短的循环放在最外层,以减少CPU跨切循环层的次数。例如示例4-4(b)的效率比示例4-4(a)的高。 for (row=0; row<100; row++) { for ( col=0; col<5; col++ ) { sum = sum + a[row][col]; } }
for (col=0; col<5; col++ )
{
for (row=0; row<100; row++)
{
sum = sum + a[row][col];
}
}
示例4-4(a) 低效率:长循环在最外层示例4-4(b) 高效率:长循环在最内层
l【建议4-4-2】如果循环体内存在逻辑判断,并且循环次数很大,宜将逻辑判断移到循环体的外面。示例4-4(c)的程序比示例4-4(d)多执行了N-1次逻辑判断。并且由于前者老要进行逻辑判断,打断了循环“流水线”作业,使得编译器不能对循环进行优化处理,降低了效率。如果N非常大,最好采用示例4-4(d)的写法,可以提高效率。如果N非常小,两者效率差别并不明显,采用示例4-4(c)的写法比较好,因为程序更加简洁。
for (i=0; i { if (condition) DoSomething(); else DoOtherthing(); }
if (condition)
{
for (i=0; i DoSomething(); } else { for (i=0; i DoOtherthing(); } 表4-4(c) 效率低但程序简洁表4-4(d) 效率高但程序不简洁 4.5 for语句的循环控制变量 l【规则4-5-1】不可在for 循环体内修改循环变量,防止for 循环失去控制。 l【建议4-5-1】建议for语句的循环控制变量的取值采用“半开半闭区间”写法。 示例4-5(a)中的x值属于半开半闭区间“0 =< x < N”,起点到终点的间隔为N,循环次数为N。 示例4-5(b)中的x值属于闭区间“0 =< x <= N-1”,起点到终点的间隔为N-1,循环次数为N。 相比之下,示例4-5(a)的写法更加直观,尽管两者的功能是相同的。 for (int x=0; x { … } for (int x=0; x<=N-1; x++) { … }
示例4-5(a) 循环变量属于半开半闭区间示例4-5(b) 循环变量属于闭区间
4.6 switch语句
有了if语句为什么还要switch语句?
switch是多分支选择语句,而if语句只有两个分支可供选择。虽然可以用嵌套的if语句来实现多分支选择,但那样的程序冗长难读。这是switch语句存在的理由。
switch语句的基本格式是:
switch (variable)
{
case value1 : …
break;
case value2 : …
break;
…
default : …
break;
}
l【规则4-6-1】每个case语句的结尾不要忘了加break,否则将导致多个分支重叠(除非有意使多个分支重叠)。
l【规则4-6-2】不要忘记最后那个default分支。即使程序真的不需要default处理,也应该保留语句default : break; 这样做并非多此一举,而是为了防止别人误以为你忘了default处理。
4.7 goto语句
自从提倡结构化设计以来,goto就成了有争议的语句。首先,由于goto语句可以灵活跳转,如果不加限制,它的确会破坏结构化设计风格。其次,goto语句经常带来错误或隐患。它可能跳过了某些对象的构造、变量的初始化、重要的计算等语句,例如:
goto state;
String s1, s2;// 被goto跳过
int sum = 0; // 被goto跳过
…
state:
…
如果编译器不能发觉此类错误,每用一次goto语句都可能留下隐患。
很多人建议废除C++/C的goto语句,以绝后患。但实事求是地说,错误是程序员自己造成的,不是goto的过错。goto 语句至少有一处可显神通,它能从多重循环体中咻地一下子跳到外面,用不着写很多次的break语句; 例如
{ …
{ …
{ …
goto error;
}
}
}
error:
…
就象楼房着火了,来不及从楼梯一级一级往下走,可从窗口跳出火坑。所以我们主张少用、慎用goto语句,而不是禁用。
篇4:c语言条件语句什么意思
一样个表达式可以包含其他表达式和运算符,并且基于整个表达式的运算结果可以得到一个真/假的'条件值。因此,当一个表达式在程序中被用于检验其真/假的值时,就称为一个条件。
一、if语句
if(表达式) 语句1;
如果表达式的值为非0,则执行语句1,否则跳过语句继续执行下面的语句。
篇5:C语言函数调用方式的区别
通常在使用VC进行函数定义时会指定该函数调用方式,诸如:
int __stdcall max(int a, int b)
{
return a>b?a:b;
}
int __cdecl min(int a, int b)
{
return a
}
bool __fastcall equal(int a, int b)
{
return a=b?true:false;
}
首先,让我们来分个类,调用方法分为两大类另加一个较特殊的__thiscall.
第一类:__stdcall类 别名:WINAPI,CALLBACK,PASCAL,该类特点是:主调函数负责参数入栈,由函数本身负责栈的恢复。
第二类:__cdecl类 别名:C/C++中默认调用方式,若你定义函数未指定函数调用约定(Calling Conventions),例如在VC6中下面两个函数的调用约定是等价的:
int max(int a, int b)
{
return a>b?a:b;
}
int __cdecl min(int a, int b)
{
return a
}
该类调用约定的特点是:由主调函数负责参数入栈,并由主调函数负责线的恢复。
第三类:__thiscall 该类比较特殊,只用于类成员函数调用,你甚至不能强制指定这个函数调用约定。它是由C/C++编译器自动添加的。在C/C++中类成员函数会默认传入一个this指针,对于此,在默入情况下,C/C++中类成员函数通过此类调用约定来指定this指针。
接着介绍一下__thiscall,__thiscall是关于类的一种调用方式。
它与其他调用方式的最大区别是:
__thiscall对每个函数都增加了一个类指针参数
class aa
{
void bb(int cc);
};
实际上bb的函数原形是void bb(aa &this, int cc);
__cdecl的调用方式介绍: C和C++缺省调用方式
例子:
void Input( int &m,int &n);/*相当于void __cdecl Input(int &m,int &n);*/
以下是相应的汇编代码:
00401068 lea eax,[ebp-8] ;取[ebp-8]地址(ebp-8),存到eax
0040106B push eax ;然后压栈
0040106C lea ecx,[ebp-4] ;取[ebp-4]地址(ebp-4),存到ecx
0040106F push ecx ;然后压栈
00401070 call @ILT+5(Input) (0040100a);然后调用Input函数
00401075 add esp,8 ;恢复栈
从以上调用Input函数的过程可以看出:在调用此函数之前,首先压栈ebp-8,然后压栈ebp-4,然后调用函数Input,最后Input函数调用结束后,利用esp+8恢复栈。由此可见,在C语言调用中默认的函数修饰_cdecl,由主调用函数进行参数压栈并且恢复堆栈。
下面看一下:地址ebp-8和ebp-4是什么? 在VC的VIEW->debug windows->Registers,显示寄存器变量值,然后在选debug windows->Memory,输入ebp-8的值和ebp-4的值(或直接输入ebp-8和-4),看一下这两个地址实际存储的是什么值,实际上是变量“n ”的地址(ebp-8),m的地址(ebp-4)。
由此可以看出:在主调用函数中进行实参的压栈并且顺序是从右到左。另外,由于实参是相应的变量的引用,也证明实际上引用传递的是变量的地址(类似指针),
总结:在C或C++语言调用中默认的函数修饰_cdecl,由主调用函数进行参数压栈并且恢复堆栈,实参的压栈顺序是从右到左,最后由主调函数进行堆栈恢复。由于主调用函数管理堆栈,所以可以实现变参函数。另外,命名修饰方法是在函数前加一个下划 线(_)。
_stdcall调用约定介绍:实际上就是PASCAL,CALLBACK,WINAPI
例子:
void WINAPI Input( int &m,int &n);
看一下相应调用的汇编代码:
00401068 lea eax,[ebp-8]
0040106B push eax
0040106C lea ecx,[ebp-4]
0040106F push ecx
00401070 call @ILT+5(Input) (0040100a)
从以上调用Input函数的过程可以看出:在调用此函数之前,首先压栈ebp-8,然后压栈ebp-4,然后调用函数Input,在调用函数Input之后,没有相应的堆栈恢复工作(为其它的函数调用,所以我没有列出)下面再列出Input函数本身的汇编代码:(实际此函数不大,但做汇编例子还是大了些,大家可以只看前和后,中间代码与此例子无关)
39: void WINAPI Input( int &m,int &n)
40: {
00401110 push ebp
00401111 mov ebp,esp
00401113 sub esp,48h
00401116 push ebx
00401117 push esi
00401118 push edi
00401119 lea edi,[ebp-48h]
0040111C mov ecx,12h
00401121 mov eax,0CCCCCCCCh
00401126 rep stos dword ptr [edi]
41: int s,i;
42:
43: while(1)
00401128 mov eax,1
0040112D test eax,eax
0040112F je Input+0C1h (004011d1)
44: {
45: printf(“Please input the first number m:”);
00401135 push offset string “ Please input the first number m”… (004260b8)
0040113A call printf (00401530)
0040113F add esp,4
46: scanf(“%d”,&m);
00401142 mov ecx,dword ptr [ebp+8]
00401145 push ecx
00401146 push offset string “%d” (004260b4)
0040114B call scanf (004015f0)
00401150 add esp,8
47:
48: if ( m= s )
004011B3 mov eax,dword ptr [ebp+8]
004011B6 mov ecx,dword ptr [eax]
004011B8 cmp ecx,dword ptr [ebp-4]
004011BB jl Input+0AFh (004011bf)
篇6:c语言:易错的if语句
易错的if语句
#include 结果: in range 请按任意键继续. . . ★ php 面试题 【C语言中表达式和表达式语句的区别(共6篇)】相关文章: 高级Java笔试题2023-11-05 基础JAVA笔试题2022-04-29 述职报告和年终总结有什么区别2022-08-25 java开发面试题型与技巧2023-12-21 java实习面试简历怎么写2023-04-10 个人工作总结与述职报告的区别2023-02-11 一份比较全的PHP笔试题2024-02-25 述职报告与个人工作总结的区别2023-08-25 儿童诗两首《我想》《童年水墨画》教学设计(人教版五年级)2023-09-30 c语言笔试题目及答案2023-06-22