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
首先我们查看上述类型原本的大小:
然后稍微更改原来的代码,使得其能够打印指针大小(为避免大量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;
}
得打印结果为:
由上图结果知,在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;
}
经过交换后,结果如下:
并使用verifier.py检查代码,结果为:
Write-up 5
我们首先将优化等级从O1更改为O3,然后运行make clean;make
,可以看到:
因为我们之前曾经使用O1优化等级编译过,输入make clean
将之前产生的可执行档及其他档案删除,即rm -f ……
部分
然后执行make
,其为 make all
的简写,它根据makefile的规则,将 .c文件以O3优化方式编译成.o文件,然后进一步产生可执行文件,即clang -o3 ……
部分
Write-up 6
键入make ASAN=1
后,看到的错误输出为:
第一部分(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);
}
更改后运行结果如下:
可知运行结果正确
Write-up 8
首先调用free_matrix
释放空间,
free_matrix(A);
free_matrix(B);
free_matrix(C);
更改后运行Valgrind检测结果为:
可知程序正确运行,无错误