zoukankan      html  css  js  c++  java
  • 家庭作业

    家庭作业一(Chapter 2)

    P80 2.56

    试用不同的示例值来运行show_bytes的代码。

    为了能方便地同屏显示多个不同的示例值结果,对原有的代码做了一定的添加修改,使得主函数main中有do-while循环。

    源代码如下:

    #include <stdio.h>
    typedef unsigned char *byte_pointer;
    void show_bytes(byte_pointer start, int len)
    {
        int i;
        for(i = 0;i<len;i++)
        {
            printf("%.2x",start[i]);
        }
        printf("
    ");
    }
    void show_int(int x)
    {
        show_bytes((byte_pointer) &x, sizeof(int));
    }
    void show_float(float x)
    {
        show_bytes((byte_pointer) &x, sizeof(float));
    }
    void show_pointer(void *x)
    {
        show_bytes((byte_pointer) &x, sizeof(void *));
    }
    void test_show_bytes(int val)
    {
        int ival = val;
        float fval = (float)ival;
        int *pval = &ival;
        printf("show_int = ");
        show_int(ival);
        printf("show_float = ");
        show_float(fval);
        printf("show_pointer = ");
        show_pointer(pval);
    }
    void main()
    {
        int val;
        char flag;
        do
        {
            printf("please enter an int:
    ");
            scanf("%d",&val);
            test_show_bytes(val);
            printf("Do you want to continue?(YY or NN)
    ");
            fflush(stdin);
            scanf("%c
    ",&flag);
            //printf("flag =%c
    ",flag);
            fflush(stdin);
        }while(flag == 'y' || flag == 'Y');
    }
    

    运行结果(以12345,23,45为例) 

    P80 2.57

    编写程序showshort,showlong,show_double,它们分别打印类型为short int,long int,double的C语言对象的字节表示。请尝试在几种机器上运行。

    与上题中的show_int函数结构类似,都是将原来的数据类型强转为字节型然后以二进制形式输出。

    C语言代码如下:

        #include <stdio.h>
    typedef unsigned char *byte_pointer;
    void show_bytes(byte_pointer start, int len)
    {
        int i;
        for(i = 0;i<len;i++)
        {
            printf("%.2x",start[i]);
        }
        printf("
    ");
    }
    void show_short(short int x)
    {
        show_bytes((byte_pointer) &x, sizeof(short int));
    }
    void show_long(long int x)
    {
        show_bytes((byte_pointer) &x, sizeof(long int));
    }
    void show_double(double x)
    {
        show_bytes((byte_pointer) &x, sizeof(double));
    }
    void test_show_bytes(short int sval)
    {
        //short int sval = val;
        long int  lval = (long int)sval;
        float fval = (float)sval;
        double dval = (double)fval;
        printf("show_short = ");
        show_short(sval);
        printf("show_long = ");
        show_long(lval);
        printf("show_double = ");
        show_double(dval);
    }
    void main()
    {
        short int sval;
        char flag;
        do
        {
            printf("please enter an short int:
    ");
            scanf("%d",&sval);
            test_show_bytes(sval);
            printf("Do you want to continue?(YY or NN)
    ");
            fflush(stdin);
            scanf("%c
    ",&flag);
            //printf("flag =%c
    ",flag);
            fflush(stdin);
        }while(flag == 'y' || flag == 'Y');
    }
    

    结果如下:

    P204 3.58

    下面的代码是在一个开关语句中进行分支选择的例子。实现各个动作的汇编代码如图中的汇编代码所示。填写C代码中缺失的那部分,注意那些会落入其他情况中的情况。

    C代码:

    typedef enum{MODE_A,MODE_B,MODE_C,MODE_D,MODE_E} mode_t;
    int switch3(int *p1,int *p2,mode_t action)
    {
        int result =0;
        switch(action)
        {
            case MODE_A:
    
            case MODE_B:
    
            case MODE_C:
    
            case MODE_D:
    
            case MODE_E:
    
            default:
    
        }
        return result;
    }
    

    汇编代码:

    .L17:
    movl $17,%edx
    jmp .L19
    .L13:
    movl 8(%ebp),%eax
    movl (%eax),%edx
    movl 12(%ebp),%ecx
    movl (%ecx),%eax
    movl %eax,(%ecx)
    jmp .L19
    .L14
    movl 12(%ebp),%edx
    movl (%edx),%eax
    movl %eax, %edx
    movl 8(%ebp),%ecx
    addl (%ecx),%edx
    movl 12(%ebp),%eax
    movl %edx,(%eax)
    jmp .L19
    .L15
    movl 12(%ebp),%edx
    movl $15,(%edx)
    movl 8(%ebp),%ecx
    movl (%ecx),%edx
    movl .L19
    .L16
    movl 8(%ebp),%edx
    movl (%edx),%eax
    movl 12(%ebp),%ecx
    movl %eax,(%ecx)
    movl $17,%edx
    .L19
    movl %edx,%eax
    

     

    分析:

     

    .L17部分:直接是result =17;

     

    .L13部分:把P1的值传给%edx;把p1(指针)传给了%ecx之后,又将p2的值传给了%ecx所指向位置——相当于让指针P1指向原P2所指向的值

     

    .L14部分:根据前面的基础,movl %edx,(%eax) 一句是让P2指向了(P1指向的值加上P2指向的值)

     

    .L15部分:直接让P2指向了15;然后让P2指向了P1指向的值

     

    .L16部分:让P2指向了P1指向的值,返回值设定为17

     

    .L19部分:直接返回了result的初始值

     

    【注意:关于可能落入其他情况中的情况;我注意到.L16部分是没有jmp .L19的语句的;然而在给出的C代码中,.L16对应的MODED之后是.L17对应的MODEE。仔细观察这两部分汇编代码,发现都有将result赋值为17的语句。所以得出,MODED落入MODEE】

     

    typedef enum{MODE_A,MODE_B,MODE_C,MODE_D,MODE_E} mode_t;
    int switch3(int *p1,int *p2,mode_t action)
    {
        int result =0;
        switch(action)
        {
            case MODE_A:
                result = *p1;
                *p1 = *p2;
                break;
            case MODE_B:
                result = *p1+*p2;
                *p2 = result;
                break;
            case MODE_C:
                result = *p1;
                *p2 =15;
                break;
            case MODE_D:
                *p2 = *p1;
            case MODE_E:
                result = 17;
                break;
            default:
                result = -1;
                break;
        }
        return result;
    }

    家庭作业二(Chapter 3)

    P206 3.60

    考虑下面的源代码,这里R,S,T都是用#define声明的常数

    int A[R][S][T];
    int store_ele(int i,int j,int k,int *dest)
    {
        *dest=A[i][j][k];
        return sizeof(A);
    }
    

    编译这个程序,GCC产生下面的汇编代码:(i at %ebp+8,j at %ebp+12,k at %ebp+16,dest at %ebp+20)

    movl 8(%ebp),%ecx
    movl 12(%ebp),%eax
    leal (%eax,%eax,8),%eax
    movl %ecx,%edx
    sall $6,%edx
    subl %ecx,%edx
    addl %edx,%eax
    addl 16(%ebp),%eax
    movl A(,%eax,4),%edx
    movl 20(%ebp),%eax
    movl %edx,(%eax)
    movl $2772,%eax
    

    A.将等式(3-1)从二维扩展到三维,提供数组元素A[i][j][k]位置的公式

    B.根据汇编代码,确定R,S,T的值

    对上面的汇编代码逐行翻译,可以得到以下内容:

    1:i
    2:j
    3:9j
    4:i
    5:64i
    6:63i
    7:63i+9j
    8:63i+9j+k
    9:A+4(63i+9j+k)
    10:dest
    11:将dest指向%edx的内容
    12:2772即A[R][S][T]的大小
    

    A.不考虑每个元素的大小,A[i][j]起始地位置是iST+jT;而A[i][j][k]起始的位置就是iST+jT+K。考虑A数组有起始位置并且数组元素也有大小(4),所以真正的地址是A(,iST+j*T+K,4)

    B.由第9行的A+4(63i+9j+k)=A(,iST+jT+K,4)可以得到:T=9;ST=63;

    再有最后的4RS*T=2772可以得出:

    R=11;S=7;T=9

    家庭作业三(第八章)

    8.10

    在这一章里,我们介绍了一些具有不寻常的调用和返回行为的函数:setjmp,longjmp,execve,fork。找到下列行为中和每个函数相匹配的一种:  A.调用一次,返回两次  B.调用一次,从不返回  C.调用一次,返回1次或者多次

    【解答】  对列举出来的函数逐个分析:

    • setjmp函数——

      • 代码:

        int setjmp(imp_buf env);返回0
        int sigsetjmp(sigjmp_buf env,int savesigs);
        
      • 解释:setjmp函数被调用一次而返回两次,依次是在保存当前环境的时候(返回0),另一次是被每一个相应的longjmp调用(返回错误类型)
    • longjmp函数——与上面的setjmp相配合使用,无返回值

      • 代码:

        void longjmp(jmp_buf env,int retval);
        void siglongjmp(sigjmp_buf env,int retval);
        
    • execve函数——

      • 代码:

        int execve(const char *filename,const char *argv[],const char *envp[]);//加载并运行可执行目标文件,如果成功则无返回值,如果不成功则返回-1
        
    • fork函数——

      • 代码:

        pid_t fork(void);//子进程返回0;父进程返回子进程的PID;如果出错,则为-1
        
      • 解释:fork函数被创建之后,将返回两次:一次返回到父进程中,一次返回到子进程中

    所以,

    A. 调用一次,返回两次: fork  B. 调用一次,从不返回: execve, longjmp  C. 调用一次,返回一次或者多次: setjmp

    8.16

    下面这个程序的输出是什么?

    #include "csapp.h"
    int counter = 1;
    int main()
    {
        if(fork() == 0)
        {
            counter--;
            exit(0);
        }
        else
        {
            Wait(NULL);
            printf("counter = %d
    ",++counter);
        }
        exit(0);
    }
    

    【解答】 首先,主函数创建了子进程,并将其返回值加入判断条件;从而使得子进程执行if语句中的命令;而父进程执行else里面的命令;子进程会使得在自己从父进程中拷贝来的数据里的counter从原有的值减一变为0;父进程执行wait之后,若子进程还未结束则被挂起,直到子进程结束,然后打印出来其数据中保存的counter加上1的结果:2

    所以答案为:counter = 2

  • 相关阅读:
    【刷题】洛谷 P3808 【模板】AC自动机(简单版)
    【刷题】BZOJ 3172 [Tjoi2013]单词
    【刷题】BZOJ 2434 [Noi2011]阿狸的打字机
    【刷题】BZOJ 1211 [HNOI2004]树的计数
    【刷题】BZOJ 1195 [HNOI2006]最短母串
    【刷题】BZOJ 1095 [ZJOI2007]Hide 捉迷藏
    【刷题】BZOJ 1030 [JSOI2007]文本生成器
    【刷题】BZOJ 3926 [Zjoi2015]诸神眷顾的幻想乡
    【刷题】BZOJ 2780 [Spoj]8093 Sevenk Love Oimaster
    【刷题】BZOJ 2753 [SCOI2012]滑雪与时间胶囊
  • 原文地址:https://www.cnblogs.com/lwr-/p/4895198.html
Copyright © 2011-2022 走看看