家庭作业
2015-10-20 16:23
375 查看
家庭作业一(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("\n"); } 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:\n"); scanf("%d",&val); test_show_bytes(val); printf("Do you want to continue?(YY or NN)\n"); fflush(stdin); scanf("%c\n",&flag); //printf("flag =%c\n",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("\n"); } 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:\n"); scanf("%d",&sval); test_show_bytes(sval); printf("Do you want to continue?(YY or NN)\n"); fflush(stdin); scanf("%c\n",&flag); //printf("flag =%c\n",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\n",++counter); } exit(0); }
【解答】 首先,主函数创建了子进程,并将其返回值加入判断条件;从而使得子进程执行if语句中的命令;而父进程执行else里面的命令;子进程会使得在自己从父进程中拷贝来的数据里的counter从原有的值减一变为0;父进程执行wait之后,若子进程还未结束则被挂起,直到子进程结束,然后打印出来其数据中保存的counter加上1的结果:2
所以答案为:counter = 2
相关文章推荐
- Android 命名规范(提高代码可以读性)
- VMware NAT Ubuntu 14.04 联网
- 【基础练习】【强连通tarjan】vijos1021-1023 Victoria的舞会系列题解
- Xcode6以后如何用企业证书发布应用
- 用户画像数据建模方法
- grid---样式
- 保研机试上机总结
- 关于自动布局的一些知识点
- html 上传文件
- Ubuntu 系统用网线连上路由器上网配置
- 【Android】Android Studio 使用第三方类库
- Java中的Arrays工具类的应用复习
- 【原创】Sliding Window Maximum 解法分析
- zTree实现目录树
- service(二) Android Studio 编写远程服务
- sql server中dense_rank和row_number
- JVM参数
- eclipse配置tomcat 8.0.24服务器
- 命令行压缩解压一 7z
- Algorithms—131.Palindrome Partitioning