C语言学习笔记 lesson10&lesson11 运算符

语句

c语言的语句通过编译器生成代码,使得程序可以执行

语句的组成

 以分号结束,由 运算符表达式关键字组成

 运算符

  sizeof 返回类型是size_t
%模运算 得出结果永远小于模数

语句的分类

赋值语句:语句中有=  数据对象: 数据所占用的空间
左值右值,=左边的数据( 代表的意义是可以被修改的值
右值,表达式等, 一般代表不可修改的值               

左值放在右值使用的时候使用的不是右值本身,而是右值中的数值。

代码举例

#define  BASE 20 

int main()

{

int i_num = 0;                                 //初始化语句

i_num = 100;                                 // 赋值语句

int sum = i_num;                          // 赋值语句

sum = 100 + 200;                        // 右值表达式

sum + i_num + sum;                  // 右值表达式

sum = BASE * 2;    

int i_other_num = sum = i_num = BASE; //连续赋值

return 0;

}

反汇编

#define  BASE 20 

int main()

{

00171650  push        ebp  

00171651  mov         ebp,esp  

00171653  sub         esp,0E4h  

00171659  push        ebx  

0017165A  push        esi  

0017165B  push        edi  

0017165C  lea         edi,[ebp-0E4h]  

00171662  mov         ecx,39h  

00171667  mov         eax,0CCCCCCCCh  

0017166C  rep stos    dword ptr es:[edi]  

每一次进入一个函数的时候,将栈顶备份,将当前函数的栈顶和栈底指针分在同一个,产生了新栈。分配了空间,再将需要备份的寄存器压进栈,将栈里的空间全部赋值为0CCCCCCCCh ,此时当前函数当中的所有局部临时变量的地址分配完成。


int i_num = 0; //初始化语句

0017166E  mov         dword ptr [i_num],0  

i_num = 100;   // 赋值语句

00171675  mov         dword ptr [i_num],64h  

int sum = i_num; // 赋值语句  把左值当成右值使用

0017167C  mov         eax,dword ptr [i_num]   第一步,转换成数值,放在eax寄存器里

0017167F  mov         dword ptr [sum],eax       第二步 , 实际赋值还是不可修改的。 

sum = 100 + 200;  // 右值表达式

00171682  mov         dword ptr [sum],12Ch  先计算,再赋值

sum + i_num + sum; // 右值表达式

sum = BASE * 2;    

00171689  mov         dword ptr [sum],28h  

int i_other_num = sum = i_num = BASE; //连续赋值 从右到左连续赋值

00171690  mov         dword ptr [i_num],14h    按照优先级分成一个个表达式

00171697  mov         eax,dword ptr [i_num]   

0017169A  mov         dword ptr [sum],eax  

0017169D  mov         ecx,dword ptr [sum]  

001716A0  mov         dword ptr [i_other_num],ecx  

                          

return 0;

001716A3  xor         eax,eax  

}

002016B7  pop         edi  

002016B8  pop         esi  

002016B9  pop         ebx  

002016BA  mov         esp,ebp  

002016BC  pop         ebp  

002016BD  ret 

函数栈在分配空间之前会对代码进行扫描,判断生成多大的空间。使用的时候不需要对变量一一分配空间。

赋值操作使用move语句,如果是一个字面值,立即数,直接放进内存;如果是一个变量,第一步先把变量的值取出来变成立即数,再把它赋值。如果有计算,先计算出值,再赋值。如果是两个变量相加,显示生成add计算;连续赋值,一个表达式有一定的优先级放在一起,按照从右到左的顺序赋值。


运算符优先级

一般会使用二叉树来定义表达式的优先级

sum = 25 + BASE *i_num / 3;

反汇编

002016A3  imul        eax,dword ptr [i_num],14h    乘法,

002016A7  cdq  

002016A8  mov         ecx,3             

002016AD  idiv        eax,ecx  

002016AF  add         eax,19h  

002016B2  mov         dword ptr [sum],eax  


sum = 25 + BASE *(i_num / 3);


002016A3  mov         eax,dword ptr [i_num]  

002016A6  cdq  

002016A7  mov         ecx,3  

002016AC  idiv        eax,ecx  

002016AE  imul        edx,eax,14h  

002016B1  add         edx,19h  

002016B4  mov         dword ptr [sum],edx


typedef unsigned int index;  //取别名(定义含义更鲜明)区分其他的变量类型

index i = BASE;

size_t sz = sizeof(index);

printf("%d", i++);                  语句执行完成后 自增

printf("%d",i );


printf("%d", ++i);                  先自增

printf("%d", i);


printf("%d", i_num*i / BASE + (sum - i--)*++i);   // 加括号,增加可读性

反汇编

index i = BASE;

012B17C7  mov         dword ptr [i],14h  

size_t sz = sizeof(index);

012B17CE  mov         dword ptr [sz],4     如果size_t是函数,会调用call指令跳转, 直接赋值说明了size_t是操作符 

printf("%d", i++);

012B17D5  mov         eax,dword ptr [i]                    把i的值先存放进exa寄存器

012B17D8  mov         dword ptr [ebp-100h],eax    放进临时变量

012B17DE  mov         ecx,dword ptr [i]       再放进ecx

012B17E1  add         ecx,1                              +1

012B17E4  mov         dword ptr [i],ecx        i已经发生了改变

012B17E7  mov         edx,dword ptr [ebp-100h]   给printf传递的是未改变的临时变量

012B17ED  push        edx  

012B17EE  push        offset string "%d" (012B6B30h)  

012B17F3  call        _printf (012B1316h)  

012B17F8  add         esp,8  

printf("%d",i );

012B17FB  mov         eax,dword ptr [i]  

printf("%d",i );

012B17FE  push        eax  

012B17FF  push        offset string "%d" (012B6B30h)  

012B1804  call        _printf (012B1316h)  

012B1809  add         esp,8  



printf("%d", ++i);

012B180C  mov         eax,dword ptr [i]  

012B180F  add         eax,1  

012B1812  mov         dword ptr [i],eax  

012B1815  mov         ecx,dword ptr [i]   把i直接传递给printf

012B1818  push        ecx  

012B1819  push        offset string "%d" (012B6B30h)  

012B181E  call        _printf (012B1316h)  

012B1823  add         esp,8  

printf("%d", i);

012B1826  mov         eax,dword ptr [i]  

012B1829  push        eax  

012B182A  push        offset string "%d" (012B6B30h)  

012B182F  call        _printf (012B1316h)  

012B1834  add         esp,8  



printf("%d", i_num*i / BASE + (sum - i--)*++i); 

012B1837  mov         eax,dword ptr [i]  

012B183A  add         eax,1  

012B183D  mov         dword ptr [i],eax  

012B1840  mov         ecx,dword ptr [sum]  

012B1843  sub         ecx,dword ptr [i]  

012B1846  imul        ecx,dword ptr [i]  

012B184A  mov         eax,dword ptr [i_num]  

012B184D  imul        eax,dword ptr [i]  

012B1851  xor         edx,edx  

012B1853  mov         esi,14h  

012B1858  div         eax,esi  

012B185A  add         eax,ecx  

012B185C  mov         dword ptr [ebp-100h],eax  

012B1862  mov         edx,dword ptr [i]  

012B1865  sub         edx,1  

012B1868  mov         dword ptr [i],edx  

012B186B  mov         eax,dword ptr [ebp-100h]  

012B1871  push        eax  

012B1872  push        offset string "%d" (012B6B30h)  

012B1877  call        _printf (012B1316h)  

012B187C  add         esp,8  

size_t 定义  (传递变量类型和变量名)

#ifdef _WIN64

    typedef unsigned __int64 size_t;

    typedef __int64          ptrdiff_t;

    typedef __int64          intptr_t;

#else

    typedef unsigned int     size_t;

    typedef int              ptrdiff_t;

    typedef int              intptr_t;

#endif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值