深入理解计算机系统期末作业

期末作业

代码1:
函数gets()的实现:

char *gets(char *dest)
{
  int c = getchar();
  char *p = dest;
  while (c != EOF && c != '\n') {
    *p++ = c;
    c = getchar();
  }
  *p = '\0';
  return dest;
}

读取输入行并将其返回:

void echo()
{
    char buf[4];
    gets(buf);
    puts(buf);
}
void call_echo()
{
    echo();
}

主程序:

int main()
{
    printf("Type a string:");
    call_echo();
    return 0;
}

下面是这个程序的运行结果:
在这里插入图片描述
这里会发现char buf[4]太小了!

代码2:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFSIZE 256

int main(int argc, char *argv[]) {
  char prefix[BUFSIZE];
  char next[BUFSIZE];
    int i;
    float sum = 0.0;
    for (i = 1; i < argc; i++) {
	float x = atof(argv[i]);
	sum += x;
	if (i == 1) {
	  sprintf(prefix, "%.4g", x);
	} else {
	  sprintf(next, " + %.4g", x);
	  strcat(prefix, next);
	  printf("%s = %.4g\n", prefix, sum);
	}
    }
    return 0;
}

下面在ubuntu上的结果:
@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out 1e20 -1e20 3.14
1e+20 + -1e+20 = 0
1e+20 + -1e+20 + 3.14 = 3.14
@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out -1e20 3.14
-1e+20 + 3.14 = -1e+20
@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out -1e20 3.14 1e20
-1e+20 + 3.14 = -1e+20
-1e+20 + 3.14 + 1e+20 = 0
这说明浮点数在运算时有可能会造成精度损失,提醒我们在写程序时应注重数据类型和处理数的方式

代码3:
将命令行上的十六进制数字序列转换为字符串,以\n结尾:

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
    int i;
    for (i = 1; i < argc; i++) {
	unsigned long dig = strtoul(argv[i], NULL, 16);
	putchar((char) dig);
    }
    putchar('\n');
    return 0;
}

输入参数:30 31 32 33 34 35 36 37 38 39 输出为:0123456789

代码4:
存入数据的地址与上一个数据的地址有关,并且会影响下一个数据的地址

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

static void show_pointer(void *p, char *descr) {
    //    printf("Pointer for %s at %p\n", descr, p);
    printf("%s\t%p\t%lu\n", descr, p, (unsigned long) p);
}

char big_array[1L<<24];    /*  16 MB */
//char huge_array[1L<<31];   /*   2 GB */
char huge_array[1L<<30];/*   1 GB */
int global = 0;

int useless() { return 0; }

int main ()
{
    void *p1, *p2, *p3, *p4;
    int local = 0;
    p1 = malloc(1L << 28);
    p2 = malloc(1L << 8);
    //p3 = malloc(1L << 32);
	p3 = malloc(1L << 16);
    p4 = malloc(1L << 8);

    show_pointer((void *) big_array, "big array");
    show_pointer((void *) huge_array, "huge array");
    show_pointer((void *) &local, "local");
    show_pointer((void *) &global, "global");
    show_pointer((void *) p1, "p1");
    show_pointer((void *) p2, "p2");
    show_pointer((void *) p3, "p3");
    show_pointer((void *) p4, "p4");
    show_pointer((void *) useless, "useless");
    show_pointer((void *) exit, "exit");
    show_pointer((void *) malloc, "malloc");
    return 0;
}

下面运行结果:
gec@ubuntu:/mnt/hgfs/share/csapp_code$ gcc locate.c
gec@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out
big array 0x4804a060 1208262752
huge array 0x804a060 134520928
local 0xbfcc9fdc 3217858524
global 0x804a044 134520900
p1 0xa7545008 2807320584
p2 0x49a67008 1235644424
p3 0x49a67110 1235644688
p4 0x49a77118 1235710232
useless 0x80484b6 134513846
exit 0x8048370 134513520
malloc 0x8048350 134513488

代码5:
深度递归示例:

#include <stdio.h>
#include <stdlib.h>

int recurse(int x) {
    int a[1<<15];  /* 4 * 2^15 =  64 KiB */
    printf("x = %d.  a at %p\n", x, a); 
    a[0] = (1<<14)-1;
    a[a[0]] = x-1;
    if (a[a[0]] == 0)
	return -1;
    return recurse(a[a[0]]) - 1;
}

int main(int argc, char *argv[]) {
    int x = 100;
    if (argc > 1)
	x = atoi(argv[1]);
    int v = recurse(x);
    printf("x = %d.  recurse(x) = %d\n", x, v);
    return 0;
}

不带参数
x = 100. a at 0xbfd3f8b0
x = 99. a at 0xbfd1f890
x = 98. a at 0xbfcff870
x = 97. a at 0xbfcdf850
x = 96. a at 0xbfcbf830
x = 95. a at 0xbfc9f810
x = 94. a at 0xbfc7f7f0
x = 93. a at 0xbfc5f7d0
x = 92. a at 0xbfc3f7b0
x = 91. a at 0xbfc1f790
x = 90. a at 0xbfbff770
x = 89. a at 0xbfbdf750
x = 88. a at 0xbfbbf730
x = 87. a at 0xbfb9f710
x = 86. a at 0xbfb7f6f0
x = 85. a at 0xbfb5f6d0
x = 84. a at 0xbfb3f6b0
x = 83. a at 0xbfb1f690
x = 82. a at 0xbfaff670
x = 81. a at 0xbfadf650
x = 80. a at 0xbfabf630
x = 79. a at 0xbfa9f610
x = 78. a at 0xbfa7f5f0
x = 77. a at 0xbfa5f5d0
x = 76. a at 0xbfa3f5b0
x = 75. a at 0xbfa1f590
x = 74. a at 0xbf9ff570
x = 73. a at 0xbf9df550
x = 72. a at 0xbf9bf530
x = 71. a at 0xbf99f510
x = 70. a at 0xbf97f4f0
x = 69. a at 0xbf95f4d0
x = 68. a at 0xbf93f4b0
x = 67. a at 0xbf91f490
x = 66. a at 0xbf8ff470
x = 65. a at 0xbf8df450
x = 64. a at 0xbf8bf430
x = 63. a at 0xbf89f410
x = 62. a at 0xbf87f3f0
x = 61. a at 0xbf85f3d0
x = 60. a at 0xbf83f3b0
x = 59. a at 0xbf81f390
x = 58. a at 0xbf7ff370
x = 57. a at 0xbf7df350
x = 56. a at 0xbf7bf330
x = 55. a at 0xbf79f310
x = 54. a at 0xbf77f2f0
x = 53. a at 0xbf75f2d0
x = 52. a at 0xbf73f2b0
x = 51. a at 0xbf71f290
x = 50. a at 0xbf6ff270
x = 49. a at 0xbf6df250
x = 48. a at 0xbf6bf230
x = 47. a at 0xbf69f210
x = 46. a at 0xbf67f1f0
x = 45. a at 0xbf65f1d0
x = 44. a at 0xbf63f1b0
x = 43. a at 0xbf61f190
x = 42. a at 0xbf5ff170
x = 41. a at 0xbf5df150
x = 40. a at 0xbf5bf130
x = 39. a at 0xbf59f110
x = 38. a at 0xbf57f0f0
段错误 (核心已转储)
输入参数如 20
x = 20. a at 0xbfb0c910
x = 19. a at 0xbfaec8f0
x = 18. a at 0xbfacc8d0
x = 17. a at 0xbfaac8b0
x = 16. a at 0xbfa8c890
x = 15. a at 0xbfa6c870
x = 14. a at 0xbfa4c850
x = 13. a at 0xbfa2c830
x = 12. a at 0xbfa0c810
x = 11. a at 0xbf9ec7f0
x = 10. a at 0xbf9cc7d0
x = 9. a at 0xbf9ac7b0
x = 8. a at 0xbf98c790
x = 7. a at 0xbf96c770
x = 6. a at 0xbf94c750
x = 5. a at 0xbf92c730
x = 4. a at 0xbf90c710
x = 3. a at 0xbf8ec6f0
x = 2. a at 0xbf8cc6d0
x = 1. a at 0xbf8ac6b0
x = 20. recurse(x) = -20

代码6:
显示字节.打印数据的字节表示:

#include <stdio.h>
/* $end show-bytes */
#include <stdlib.h>
#include <string.h>
/* $begin show-bytes */

typedef unsigned char *byte_pointer;
//typedef char *byte_pointer;
//typedef int *byte_pointer;

void show_bytes(byte_pointer start, size_t len) {
    size_t i;
    for (i = 0; i < len; i++)
	printf("%p\t0x%.2x\n", &start[i], 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 *));
}
/* $end show-bytes */


/* $begin test-show-bytes */
void test_show_bytes(int val) {
    int ival = val;
    //float fval = (float) ival;
	double fval = (double) ival;
    int *pval = &ival;
    printf("Stack variable ival = %d\n", ival);
    printf("(int)ival:\n");
    show_int(ival);
    printf("(float)ival:\n");
    show_float(fval);
    printf("&ival:\n");
    show_pointer(pval);
}
/* $end test-show-bytes */

void simple_show_a() {
/* $begin simple-show-a */
int val = 0x87654321;
byte_pointer valp = (byte_pointer) &val;
show_bytes(valp, 1); /* A. */
show_bytes(valp, 2); /* B. */
show_bytes(valp, 3); /* C. */
/* $end simple-show-a */
}

void simple_show_b() {
/* $begin simple-show-b */
int val = 0x12345678;
byte_pointer valp = (byte_pointer) &val;
show_bytes(valp, 1); /* A. */
show_bytes(valp, 2); /* B. */
show_bytes(valp, 3); /* C. */
/* $end simple-show-b */
}

void float_eg() {
  int x = 3490593;
  float f = (float) x;
  printf("For x = %d\n", x);
  show_int(x);
  show_float(f);

  x = 3510593;
  f = (float) x;
  printf("For x = %d\n", x);
  show_int(x);
  show_float(f);

}

void string_ueg() {
/* $begin show-ustring */
const char *s = "ABCDEF";
show_bytes((byte_pointer) s, strlen(s)); 
/* $end show-ustring */
}

void string_leg() {
/* $begin show-lstring */
const char *s = "abcdef";
show_bytes((byte_pointer) s, strlen(s)); 
/* $end show-lstring */
}

void show_twocomp() 
{
/* $begin show-twocomp */
    short x = 12345; 
    short mx = -x; 
    
    show_bytes((byte_pointer) &x, sizeof(short)); 
    show_bytes((byte_pointer) &mx, sizeof(short)); 
/* $end show-twocomp */
}

int main(int argc, char *argv[])
{
    int val = 12345;
    if (argc > 1) {
        val = strtol(argv[1], NULL, 0);
	printf("calling test_show_bytes\n");
	test_show_bytes(val);
    } else {
	printf("calling show_twocomp\n");
	show_twocomp();
	printf("Calling simple_show_a\n");
	simple_show_a();
	printf("Calling simple_show_b\n");
	simple_show_b();
	printf("Calling float_eg\n");
	float_eg();
	printf("Calling string_ueg\n");
	string_ueg();
	printf("Calling string_leg\n");
	string_leg();
    }
    return 0;
}

不带参数的运行结果
calling show_twocomp
0xbfa18b4c 0x39
0xbfa18b4d 0x30

0xbfa18b4e 0xc7
0xbfa18b4f 0xcf

Calling simple_show_a
0xbfa18b48 0x21

0xbfa18b48 0x21
0xbfa18b49 0x43

0xbfa18b48 0x21
0xbfa18b49 0x43
0xbfa18b4a 0x65

Calling simple_show_b
0xbfa18b48 0x78

0xbfa18b48 0x78
0xbfa18b49 0x56

0xbfa18b48 0x78
0xbfa18b49 0x56
0xbfa18b4a 0x34

Calling float_eg
For x = 3490593
0xbfa18b30 0x21
0xbfa18b31 0x43
0xbfa18b32 0x35
0xbfa18b33 0x00

0xbfa18b30 0x84
0xbfa18b31 0x0c
0xbfa18b32 0x55
0xbfa18b33 0x4a

For x = 3510593
0xbfa18b30 0x41
0xbfa18b31 0x91
0xbfa18b32 0x35
0xbfa18b33 0x00

0xbfa18b30 0x04
0xbfa18b31 0x45
0xbfa18b32 0x56
0xbfa18b33 0x4a

Calling string_ueg
0x8048940 0x41
0x8048941 0x42
0x8048942 0x43
0x8048943 0x44
0x8048944 0x45
0x8048945 0x46

Calling string_leg
0x8048947 0x61
0x8048948 0x62
0x8048949 0x63
0x804894a 0x64
0x804894b 0x65
0x804894c 0x66

gec@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out 1073741824
calling test_show_bytes
Stack variable ival = 1073741824
(int)ival:
0xbfd40020 0x00
0xbfd40021 0x00
0xbfd40022 0x00
0xbfd40023 0x40

(float)ival:
0xbfd40020 0x00
0xbfd40021 0x00
0xbfd40022 0x80
0xbfd40023 0x4e

&ival:
0xbfd40020 0x34
0xbfd40021 0x00
0xbfd40022 0xd4
0xbfd40023 0xbf

代码7:
返回整型数据的二次方:

#include <stdio.h>
#include <stdlib.h>

int sq(int x) {
    return x*x;
}

int main(int argc, char *argv[]) {
    int i;
    for (i = 1; i < argc; i++) {
	int x = atoi(argv[i]);
	int sx = sq(x);
	printf("sq(%d) = %d\n", x, sx);
    }
    return 0;
}

有结果如下:
@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out
@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out 12
sq(12) = 144
@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out 65535
sq(65535) = -131071
@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out 40000
sq(40000) = 1600000000
@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out 50000
sq(50000) = -1794967296
@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out 400000
sq(400000) = 1086210048
@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out 500000
sq(500000) = 891896832
这例说明整型数据相乘时有可能会出现溢出问题,而造成结果不符合实际。
显然程序代码没有问题时,输入的数据是有范围的,如果不注重底层的这些要求,则可能会出现意想不到的结果。
代码8:
结构体的相关问题:

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int a[2];
    double d;
} struct_t;

double fun(int i) {
    volatile struct_t s;
    s.d = 3.14;
    s.a[i] = 1073741824; /* Possibly out of bounds */
    return s.d; /* Should be 3.14 */
}

int main(int argc, char *argv[]) {
    int i = 0;
    if (argc >= 2)
	i = atoi(argv[1]);
    double d = fun(i);
    printf("fun(%d) --> %.10f\n", i, d);
    return 0;
}

运行结果如下:
gec@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out 0
fun(0) --> 3.1400000000
gec@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out 1
fun(1) --> 3.1400000000
gec@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out 2
fun(2) --> 3.1399998665
gec@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out 3
fun(3) --> 2.0000006104
gec@ubuntu:/mnt/hgfs/share/csapp_code$ ./a.out 4
fun(4) --> 3.1400000000
段错误 (核心已转储)
这例说明,结构体是一个存储区域,是有一定大小的,所以是可能出界的
这提醒我们应该在做结构体时,要注意这类相关问题,否则可能会出现意想不到的问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值