zoukankan      html  css  js  c++  java
  • 【C】貌似不友好的scanf()

    scanf语句执行过程:

    (1)逆序取参数的偏移地址并分别入栈。

    (2)根据控制字符串的格式说明符从缓冲区取数据给各变量赋值。

        ①若格式说明符是数值类数据:如果从缓冲区中拿出的第一个字符可以合法表示该数值类型数据(如对应%d的可以是任何数字字符、+、-;若对应%x,则除了以上还有字母a—b也可,and so forth...),然后取下一个字符,直到非合法字符,则认为该数值读取完毕并把该非法字符送回缓冲区。把之前取得的合法字符串转换成相应的数值类型并赋值。

    如果从缓冲区中拿出的第一个字符对应格式说明符来说不是合法字符则直接把该非法字符送回缓冲区,在不给当前变量赋值的情况下结束该条语句。如:

     1 #include<stdio.h>
     2 int main ( )
     3 {
     4     int a,i=0;
     5     printf("%d
    ",a);
     6     while(i<5)
     7     {scanf("%d",&a);
     8     printf("%d
    ",a);
     9     i++;
    10     }    
    11     return 0;
    12 }

    程序执行如下图(其中第2行的a为输入回显)

    ②若格式说明符是c%则对所有输入内容都认为是合法并给变量赋值。

    ③若格式说明符是s%,则从第一个非空白字符开始认为合法字符直到遇到空白字符。

    VC6.0反汇编结果(可以看出scanf函数取参数表中取地址的顺序与printf相同,都是倒着。)

     1 1:    #include<stdio.h>
     2 2:    int main (void)
     3 3:    {
     4 00401010   push        ebp
     5 00401011   mov         ebp,esp
     6 00401013   sub         esp,50h
     7 00401016   push        ebx
     8 00401017   push        esi
     9 00401018   push        edi
    10 00401019   lea         edi,[ebp-50h]
    11 0040101C   mov         ecx,14h
    12 00401021   mov         eax,0CCCCCCCCh
    13 00401026   rep stos    dword ptr [edi]
    14 4:        int i=0;
    15 00401028   mov         dword ptr [ebp-4],0
    16 5:        char a,b,c;
    17 6:        printf("%c
    ",a);
    18 0040102F   movsx       eax,byte ptr [ebp-8]
    19 00401033   push        eax
    20 00401034   push        offset string "%c
    " (00425fa4)
    21 00401039   call        printf (00401100)
    22 0040103E   add         esp,8
    23 7:        while(i<5)
    24 00401041   cmp         dword ptr [ebp-4],5
    25 00401045   jge         main+77h (00401087)
    26 8:        {scanf("%c%c%c",&a,&b,&c);
    27 00401047   lea         ecx,[ebp-10h];取变量c的偏移地址
    28 0040104A   push        ecx
    29 0040104B   lea         edx,[ebp-0Ch];取变量b的偏移地址
    30 0040104E   push        edx
    31 0040104F   lea         eax,[ebp-8] ;取变量a的偏移地址
    32 00401052   push        eax
    33 00401053   push        offset string "%c" (0042501c)
    34 00401058   call        scanf (004010a0)
    35 0040105D   add         esp,10h
    36 9:        printf("%c%c%c
    ",a,b,c);
    37 00401060   movsx       ecx,byte ptr [ebp-10h]
    38 00401064   push        ecx
    39 00401065   movsx       edx,byte ptr [ebp-0Ch]
    40 00401069   push        edx
    41 0040106A   movsx       eax,byte ptr [ebp-8]
    42 0040106E   push        eax
    43 0040106F   push        offset string "%c%c%c
    " (00426000)
    44 00401074   call        printf (00401100)
    45 00401079   add         esp,10h
    46 10:       i++;
    47 0040107C   mov         ecx,dword ptr [ebp-4]
    48 0040107F   add         ecx,1
    49 00401082   mov         dword ptr [ebp-4],ecx
    50 11:       }
    51 00401085   jmp         main+31h (00401041)
    52 12:       return 0;
    53 00401087   xor         eax,eax
    54 13:   }
    55 00401089   pop         edi
    56 0040108A   pop         esi
    57 0040108B   pop         ebx
    58 0040108C   add         esp,50h
    59 0040108F   cmp         ebp,esp
    60 00401091   call        __chkesp (00401180)
    61 00401096   mov         esp,ebp
    62 00401098   pop         ebp
    63 00401099   ret

     以上。

  • 相关阅读:
    C# 网络编程之基于SMTP发送电子邮件
    C#实现邮件发送的功能
    Java发邮件基础篇
    java发送邮件高级篇
    Windows下bat脚本自动发邮件
    Python发送QQ邮件
    信息系统项目管理师EV、PV、AC、BAC、CV、SV、EAC、ETC、CPI、SPI概念说明
    DOS命令整理
    JAVA对时间的操作
    JAVA 调用HTTP接口POST或GET实现方式(转)
  • 原文地址:https://www.cnblogs.com/wxiaoli/p/5313417.html
Copyright © 2011-2022 走看看