Martian148's blog Martian148's blog
首页
  • ICPC 算法笔记
  • ICPC 算法题解
  • 体系结构
  • 高等数学
  • 线性代数
  • 概率论与数理统计
  • 具体数学
  • Martian148的奇思妙想
  • 游记
  • 通识课笔记
关于
  • useful 网站
  • 友情链接
  • 分类
  • 归档

Martian148

一只热爱文科的理科生
首页
  • ICPC 算法笔记
  • ICPC 算法题解
  • 体系结构
  • 高等数学
  • 线性代数
  • 概率论与数理统计
  • 具体数学
  • Martian148的奇思妙想
  • 游记
  • 通识课笔记
关于
  • useful 网站
  • 友情链接
  • 分类
  • 归档
  • ACM - ICPC

  • 编程语言

  • 体系结构

    • 计算机组成原理笔记
    • CS61C

      • RISC-V速查表
      • CS61C Lab1
      • CS61C Lab2
        • CS61C Lab3
      • CSAPP

    • Web

    • 人工智能

    • 计算机网络

    • 数据库

    • 编程工具

    • 计算机科学
    • 体系结构
    • CS61C
    martian148
    2025-04-26
    目录

    CS61C Lab2

    # Lab 2

    # Exercise 0: Makefiles

    这个 Exercise 要求我们学会使用 Makefile 来编译 C 语言程序

    题目给出了一个 makefile

    UNAME_S := $(shell uname -s)
    CC=gcc
    LD=gcc
    CFLAGS=-ggdb -Wall -std=c99
    LDFLAGS=
    
    ifeq ($(UNAME_S), Darwin)
        MEMCHECK=valgrind --tool=memcheck --leak-check=full --track-origins=yes --dsymutil=yes
    endif
    
    ifeq ($(UNAME_S), Linux)
        MEMCHECK=valgrind --tool=memcheck --leak-check=full --track-origins=yes
    endif
    
    BIT_OPS_OBJS = bit_ops.o test_bit_ops.o
    BIT_OPS_PROG = bit_ops
    
    LFSR_OBJS = lfsr.o test_lfsr.o
    LFSR_PROG = lfsr
    
    VECTOR_OBJS=vector.o vector-test.o
    VECTOR_PROG=vector-test
    
    BINARIES=$(VECTOR_PROG) $(BIT_OPS_PROG) $(LFSR_PROG)
    
    all: $(BINARIES)
    
    $(BIT_OPS_PROG): $(BIT_OPS_OBJS)
    	$(CC) $(CFLAGS) -g -o $(BIT_OPS_PROG) $(BIT_OPS_OBJS) $(LDFLAGS)
    
    $(LFSR_PROG): $(LFSR_OBJS)
    	$(CC) $(CFLAGS) -g -o $(LFSR_PROG) $(LFSR_OBJS) $(LDFLAGS)
    
    lfsr.c: lfsr.h
    test_lfsr.c: lfsr.h
    
    bit_ops.c: bit_ops.h
    test_bit_ops.c: bit_ops.h
    
    .c.o:
    	$(CC) -c $(CFLAGS) $<
    
    vector-memcheck: $(VECTOR_PROG)
    	$(MEMCHECK) ./$(VECTOR_PROG)
    
    clean:
    	-rm -rf core *.o *~ "#"*"#" Makefile.bak $(BINARIES) *.dSYM
    
    vector.c: vector.h
    vector-test.c: vector.h
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50

    然后给出了 10 个问题

    1. Which target is part of a rule that deletes all the compiled programs? 哪个目标是删除所有编译程序的规则的一部分?
    clean
    
    1
    1. Which target is part of a rule that makes all the compiled programs? 哪个目标是创建所有编译程序的规则的一部分?
    all
    
    1
    1. Which compiler is currently being used?
    CC = gcc
    
    1
    1. What C standard are we currently using?
    CFLAGS = -ggdb -Wall -std=c99
    
    1
    1. How would we reference a variable “FOO” in a makefile?
    $(FOO)
    
    1
    1. What operating system does the term “Darwin” represent?
    "Darwin"代表的是 macOS(和 iOS 等苹果操作系统)的底层核心操作系统。
    
    1
    1. What line creates the lfsr program from its object files? (Give its line number.)
    $(LFSR_PROG): $(LFSR_OBJS)           # 行号:假设为第 24 行
        $(CC) $(CFLAGS) -g -o $@ $^ $(LDFLAGS)  # 行号:第 25 行(实际编译命令)
    
    1
    2

    # Exercise 1: Bit Operations

    编写程序完成 get_bit,set_bit,flip_bit

    #include <stdio.h>
    #include "bit_ops.h"
    
    // Return the nth bit of x.
    // Assume 0 <= n <= 31
    unsigned get_bit(unsigned x,
                     unsigned n) {
        // YOUR CODE HERE
        return (x >> n) & 1;
        // Returning -1 is a placeholder (it makes
        // no sense, because get_bit only returns 
        // 0 or 1)
        return -1;
    }
    // Set the nth bit of the value of x to v.
    // Assume 0 <= n <= 31, and v is 0 or 1
    void set_bit(unsigned * x,
                 unsigned n,
                 unsigned v) {
        // YOUR CODE HERE
        if (v == 1) 
            *x |= (1 << n);
        else
            *x &= ~(1 << n);
    }
    // Flip the nth bit of the value of x.
    // Assume 0 <= n <= 31
    void flip_bit(unsigned * x,
                  unsigned n) {
        (*x) ^= (1 << n);
        // YOUR CODE HERE
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32

    # Exercise 2: Linear Feedback Shift Register

    这个 Exercise 要求你实现一个线性反馈移位寄存器,这个图好像挂了

    根据描述很容易

    void lfsr_calculate(uint16_t *reg) {
        /* YOUR CODE HERE */
        int lfsr = *reg;
        uint16_t bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5)) & 1;
        lfsr = (lfsr >> 1) | (bit << 15);
        *reg = lfsr;
    }
    
    1
    2
    3
    4
    5
    6
    7

    # Exercise 3: Memory Management

    在本 Exercise,程序实现了一个可变数组 vector 的框架,他要求我们阅读代码并回答问题?

    为什么 bad_vector_new() 是不好的?

    /* Bad example of how to create a new vector */
    vector_t *bad_vector_new() {
        /* Create the vector and a pointer to it */
        vector_t *retval, v;
        retval = &v;
    
        /* Initialize attributes 初始化 */
        retval->size = 1;
        retval->data = malloc(sizeof(int));
        if (retval->data == NULL) {
            allocation_failed();
        }
    
        retval->data[0] = 0;
        return retval;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    这里的 retval 指向了一个由栈内存的变量 v 这个变量在函数运行结束后会被自动释放掉

    vector_t also_bad_vector_new() {
        /* Create the vector */
        vector_t v;
    
        /* Initialize attributes */
        v.size = 1;
        v.data = malloc(sizeof(int));
        if (v.data == NULL) {
            allocation_failed();
        }
        v.data[0] = 0;
        return v;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    also_bad_vector_new 这段代码也不太好的原因是,v.data = malloc(sizeof(int)); 这里申请的内存在堆内存上

    然后返回的时候发生了浅拷贝,如果调用者不自己手动释放内存就会导致内存泄漏

    然后我们完善 vector.c 和 vector.c

    /* Include the system headers we need */
    #include <stdlib.h>
    #include <stdio.h>
    
    /* Include our header */
    #include "vector.h"
    
    /* Define what our struct is */
    struct vector_t {
        size_t size;
        int *data;
    };
    
    /* Utility function to handle allocation failures. In this
       case we print a message and exit. */
    static void allocation_failed() {
        fprintf(stderr, "Out of memory.\n");
        exit(1);
    }
    
    /* Bad example of how to create a new vector */
    vector_t *bad_vector_new() {
        /* Create the vector and a pointer to it */
        vector_t *retval, v;
        retval = &v;
    
        /* Initialize attributes 初始化 */
        retval->size = 1;
        retval->data = malloc(sizeof(int));
        if (retval->data == NULL) {
            allocation_failed();
        }
    
        retval->data[0] = 0;
        return retval;
    }
    
    /* Another suboptimal way of creating a vector */
    vector_t also_bad_vector_new() {
        /* Create the vector */
        vector_t v;
    
        /* Initialize attributes */
        v.size = 1;
        v.data = malloc(sizeof(int));
        if (v.data == NULL) {
            allocation_failed();
        }
        v.data[0] = 0;
        return v;
    }
    
    /* Create a new vector with a size (length) of 1
       and set its single component to zero... the
       RIGHT WAY */
    vector_t *vector_new() {
        /* Declare what this function will return */
        vector_t *retval;
    
        /* First, we need to allocate memory on the heap for the struct */
        retval = malloc(sizeof (vector_t));
    
        /* Check our return value to make sure we got memory */
        if (retval == NULL) {
            allocation_failed();
        }
    
        /* Now we need to initialize our data.
           Since retval->data should be able to dynamically grow,
           what do you need to do? */
        retval->size = 1;
        retval->data = malloc(sizeof(int));
    
        /* Check the data attribute of our vector to make sure we got memory */
        if (retval->data == NULL) {
            free(retval);				//Why is this line necessary?
            allocation_failed();
        }
    
        /* Complete the initialization by setting the single component to zero */
        retval->data[0] = 0;
    
        /* and return... */
        return retval;
    }
    
    /* Return the value at the specified location/component "loc" of the vector */
    int vector_get(vector_t *v, size_t loc) {
    
        /* If we are passed a NULL pointer for our vector, complain about it and exit. */
        if(v == NULL) {
            fprintf(stderr, "vector_get: passed a NULL vector.\n");
            abort();
        }
    
        /* If the requested location is higher than we have allocated, return 0.
         * Otherwise, return what is in the passed location.
         */
        if (loc < v->size) {
            return v->data[loc];
        } else {
            return 0;
        }
    }
    
    /* Free up the memory allocated for the passed vector.
       Remember, you need to free up ALL the memory that was allocated. */
    void vector_delete(vector_t *v) {
        /* YOUR SOLUTION HERE */
        if (v == NULL) {
            fprintf(stderr, "vector_delete: passed a NULL vector.\n");
            abort();
        }
        /* Free the data array */
        free(v->data);
    }
    
    /* Set a value in the vector. If the extra memory allocation fails, call
       allocation_failed(). */
    void vector_set(vector_t *v, size_t loc, int value) {
        /* What do you need to do if the location is greater than the size we have
         * allocated?  Remember that unset locations should contain a value of 0.
         */
    
        if (v == NULL) {
            fprintf(stderr, "vector_set: passed a NULL vector.\n");
            abort();
        }
    
        if (loc >= v->size) {
            size_t new_size = loc + 1;
            int *new_data = realloc(v->data, new_size * sizeof(int));
            if (new_data == NULL) {
                allocation_failed();
            }
            v->data = new_data;
            for (size_t i = v->size; i < new_size; i++) {
                v->data[i] = 0;
            }
            v->size = new_size;
        }
    
        v->data[loc] = value;
        /* YOUR SOLUTION HERE */
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    #ifndef CS61C_VECTOR_H_
    #define CS61C_VECTOR_H_
    /* vector.h originally written by Jeremy Huddleston <jeremyhu@eecs.berkeley.edu> Sp2004
     *
     * So it looks like you've decided to venture into the "other" files of this
     * lab.  Good.  C Header files (the .h extension) are a way of telling other .c
     * files what they can have access to.  You usually include stdlib.h in your
     * C programs, and this process is identical to including this .h file with the
     * one change being:
     *
     * #include "file.h" 
     * versus
     * #include <file.h>
     *	 
     * The difference is that the <> notation is for system header files and the ""
     * is for ones you provide yourself (in your local directory for instance).
     *	 
     * The header file starts off with
     * #ifndef CS61C_VECTOR_H_
     * #define CS61C_VECTOR_H_
     *	 
     * and ends with a final #endif.  This prevents the file from being included
     * more than once which could've possibly resulted in an infinite loop of
     * file inclusions.
     *
     * First, we define the 'vector_t' datatype.  This next line says that a 'vector_t'
     * is the same as a 'struct vector_t'.  So anywhere in the code after this, we
     * can use 'vector_t *' to mean a pointer to a 'struct vector_t' (which is defined in
     * vector.c).  We can get away with doing this even though we don't know what a
     * struct vector is because all struct pointers have the same representation in memory.
     */
    
    #include <sys/types.h>
    
    typedef struct vector_t vector_t;
    
    /*
     *  Next, we provide the prototypes for the functions defined in vector.c.  This
     *  is a way of telling the .c files that #include this header what they will
     *  have access to.
     */
    
    /* Create a new vector */
    vector_t *vector_new();
    
    /* Free up the memory allocated for the passed vector */
    /* YOUR CODE HERE */
    void vector_delete(vector_t *v);
    
    void vector_set(vector_t *v, size_t loc, int value);
    
    /* Return the value in the vector */
    int vector_get(vector_t *v, size_t loc);
    
    /* Set a value in the vector */
    /* YOUR CODE HERE */
    
    #endif
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    CS61C Lab1
    CS61C Lab3

    ← CS61C Lab1 CS61C Lab3→

    最近更新
    01
    计算机网络笔记
    06-13
    02
    LLM101 NLP学习笔记
    06-02
    03
    《python科学计算入门》学习笔记
    05-30
    更多文章>
    Theme by Vdoing | Copyright © 2024-2025 Martian148 | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式