Write-up 2

const char* 与 char const*是指向常量的指针,即指针所指向的数据不可更改,指针本身可以更改;

char *const 是指针本身是常量,即指针本身不可更改,但所指向的数据可以更改;

const char *const为指向常量的常量指针,即指针本身与所指向的数据皆不可更改

const char *pcc = c;
char const *pcc2 = c;
char *const cp = c;
const char *const cpc = c;

我们由上定义了pcc、pcc2为指向常量的指针,cp为常量指针,cpc为指向常量的常量指针

*pcc = '7';    //*pcc为引用所指向的常量,本语句对其赋值,试图更改常量,故为不合法语句
pcc = *pcp;    // pcc为一普通指针,*pcp也为一指针,可以被合法赋值更改
pcc = argv[0]; // argv为一二重指针,argv[0]仍为一指针,可以通过合法赋值更改指针pcc的指向

cp = *pcp;     // cp为一常量指针不可更改,*pcp为一其他指针,无法对其赋值更改指向对象,故为不合法语句
cp = *argv     //*argv == *pcp,故不合法理由同上
*cp = '!';     //*cp所引用的对象并非常量,故可以通过合法赋值更改其值

cpc = *pcp;    // cpc为一不可更改的常量指针,故赋值语句不合法
cpc = argv[0]; // argv[0]为一指针,但cpc常量指针不可更改,故不合法
*cpc = '@';    // *cpc所引用的对象为常量,不可通过赋值语句修改,故不合法

Write-up 3

首先我们查看上述类型原本的大小:

image-20220910153020227

然后稍微更改原来的代码,使得其能够打印指针大小(为避免大量printf的copy,使用宏定义规定了PRINT_SIZE函数,对类型名进行字符化使之可以直接被字符串打印,简化输入),数组与结构体无法通过规格化直接打印,因此定义两个指针分别指向数组和结构体,并使用&获取其地址。

// Copyright (c) 2012 MIT License by 6.172 Staff

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

#define PRINT_SIZE(type) printf("size of *%s : %zu bytes \n", #type, sizeof(type*))

int main() {
  typedef struct {
    int id;
    int year;
  } student;

  student you;
  you.id = 12345;
  you.year = 4;

  int x[5];

  PRINT_SIZE(int);
  PRINT_SIZE(short);
  PRINT_SIZE(long);
  PRINT_SIZE(char);
  PRINT_SIZE(float);
  PRINT_SIZE(double);
  PRINT_SIZE(unsigned int);
  PRINT_SIZE(long long);

  PRINT_SIZE(uint8_t);
  PRINT_SIZE(uint16_t);
  PRINT_SIZE(uint32_t);
  PRINT_SIZE(uint64_t);
  PRINT_SIZE(uint_fast8_t);
  PRINT_SIZE(uint_fast16_t);
  PRINT_SIZE(uintmax_t);
  PRINT_SIZE(intmax_t);
  PRINT_SIZE(__int128);

  int *p1 = &x;
  struct student *p2 = &you;
  printf("size of %s : %zu bytes \n", "*x", sizeof(p1));
  printf("size of %s : %zu bytes \n", "*student", sizeof(p2));

  return 0;
}

得打印结果为:

image-20220910155955620

由上图结果知,在64位计算机上,各类型的指针的大小都为8字节


Write-up 4

因为原本函数只是按值传递,函数里形参的改变无法更改实参,所以我们可以通过指针将参数的地址传入函数,在同一地址上的修改可以更改参数,并使用解引用交换指针指向的对象的值,代码如下:

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

void swap(int *i, int *j) {
  int temp = *i;
  *i = *j;
  *j = temp;
}

int main() {
  int k = 1;
  int m = 2;
  swap(&k, &m);
  printf("k = %d, m = %d\n", k, m);

  return 0;
}

经过交换后,结果如下:

image-20220910161844157

并使用verifier.py检查代码,结果为:

image-20220910163427189


Write-up 5

我们首先将优化等级从O1更改为O3,然后运行make clean;make,可以看到:

image-20220910163855821

因为我们之前曾经使用O1优化等级编译过,输入make clean 将之前产生的可执行档及其他档案删除,即rm -f ……部分

然后执行make,其为 make all 的简写,它根据makefile的规则,将 .c文件以O3优化方式编译成.o文件,然后进一步产生可执行文件,即clang -o3 ……部分


Write-up 6

键入make ASAN=1后,看到的错误输出为:

image-20220910173730383

第一部分(ERROR):指出错误类型为detected memory leaks,即内存泄漏 第二部分:给出详细的错误信息,Direct leak of ** byte(s) in ** object(s),给出了具体发生错误的对象名、源文件位置和行数 第三部分(SUMMARY):总结上述信息,即在18个分配中泄漏了336字节


Write-up 7

查看代码可知,原代码对矩阵C没有初始化,则在计算中可能发生错误,故应对其中每一值赋0,代码更改如下:

// Allocate a buffer big enough to hold the matrix.
  new_matrix->values = (int**)malloc(sizeof(int*) * rows);
  for (int i = 0; i < rows; i++) {
    new_matrix->values[i] = (int*)malloc(sizeof(int) * cols); // ERROR
    memset((int*)(new_matrix->values[i]), 0, sizeof(int) * cols);
  }

更改后运行结果如下:

image-20220910230854076

image-20220910230926917

可知运行结果正确


Write-up 8

首先调用free_matrix释放空间,

  free_matrix(A);
  free_matrix(B);
  free_matrix(C);

更改后运行Valgrind检测结果为:

image-20220910231411224

可知程序正确运行,无错误