CS50X week4 学习笔记

week 4 Memory

十六进制

介绍十六进制:两位数的十六进制 FF,表示十进制的 255

为什么要使用十六进制? 可以表示得更简洁

eg:
二进制 11111111 -> 十六进制 0xFF
#include <stdio.h>

int main(void)
{
    int n = 50;
    printf("%i\n", n);
}

// 50 被记录在电脑的内存中,程序员通过 n 可以访问
// 1 个整数用 4 个 bites 表示
两个新的运算符
  • &:在变量前加,可以得到存储变量的内存地址

    int n = 50;
    printf("%p\n", &n);
    
  • *:有两个作用

    • 在声明变量时使用,代表这个变量存储的是相应的内存地址
    • 在使用该变量时加上,则代表指向该内存地址中的值
    int n = 50;
    int *p = &n; // 存储内存地址
    printf("%i\n", *p); // 去p存储的地址
    

    1702128473348

    1702128503253

指针
  • 含义:指针是计算机内存中某个东西的地址
  • 表示方式:int/string… *p ;叫做指针 p,p是变量名
  • 指针在内存中是 8 位
  • 字符串变量存储的是字符串第一个字符的地址

1702128549837

指针的运算

在 C 中并没有 string 这一结构类型,是在 cs50.h 的头文件中定义的,根据字符串变量存储的是字符串第一个字符的地址这一特性

typedef char *string;

char *s = "HI!"; // 指针 s 存储的是地址
    printf("%p\n", s); // 打印存储的地址
    printf("%s\n", s); // printf 可以将指向地址的所有内容转换出来,所以可以不用 *s(打印单个字符)

	printf("%c\n", *s); // H
    printf("%c\n", *(s+1)); // I
    printf("%c\n", *(s+2)); // !
字符串比较

为什么字符串判断相等不能用 == 而需要使用 strcmp 函数进行比较?

== 是比较两边内存地址,而不是逐个进行字符比较

其余的数据类型可以使用 == 比较,字符串是特殊的,设计如此

1702128674561

字符串的复制
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
    // Get a string
    string s = get_string("s: ");

    // Copy string's address
    string t = s;

    // Capitalize first letter in string
    //t[0] = toupper(t[0]);
    
    if (strlen(t) > 0)
    {
        t[0] = toupper(t[0]);
    }

    // Print string twice
    printf("s: %s\n", s);
    printf("t: %s\n", t);
}

1702128808998

为什么结果会是如此?

因为复制的字符串的内存地址,使得 t 和 s 指向相同的内容

1702128939195

正确的复制(使用两种新的函数):

  • malloc:分配一定数量的内存地址
  • free:释放被分配的内存

如果不将最后的 NULL 复制过来,在打印的时候会在最后一直打印随机字符,直到出现 NULL 后才会停止

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

int main(void)
{
    // Get a string
    string s = get_string("s: ");

    // Copy string's address
    int l = strlen(s);
    
    // 分配内存地址
    // 加1 是因为需要最后一个 NUL 字符
    string t = malloc(l + 1);

    // 复制里面的字符串,NUL 也需要复制
    // for(int i = 0, n = strlen(s); i < n; i++)
    // for (int i = 0; i < l+1; i++)
    // {
    //     t[i] = s[i];
    // }
    strcpy(t, s);

    // Capitalize first letter in string
    if (strlen(t) > 0)
    {
        t[0] = toupper(t[0]);
    }


    // Print string twice
    printf("s: %s\n", s);
    printf("t: %s\n", t);
}

1702129702768

1702129781956

复制程序优化:

  • 当输入的字符串是无限长时,get_string 会返回 NULL(代表地址0),所以要检查返回值是否为 NULL
  • malloc 同理
  • 在使用 malloc 分配内存之后,使用完成后一定要记得将分配的内存释放
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    // Get a string
    string s = get_string("s: ");
    if (s == NULL)
    {
        return 1;
    }

    // 分配内存地址
    // 加1 是因为需要最后一个 NULL 字符
    string t = malloc(strlen(s) + 1);
    if (t == NULL)
    {
        return 1;
    }

    // 复制里面的字符串,NULL 也需要复制
    strcpy(t, s);

    // Capitalize first letter in string
    if (strlen(t) > 0)
    {
        t[0] = toupper(t[0]);
    }


    // Print string twice
    printf("s: %s\n", s);
    printf("t: %s\n", t);

    // 释放
    free(t);

    return 0;
}

Valgrind

检查内存泄露的方法:

编译运行之后,使用 valgrind ./memory

垃圾数据

当声明了某个变量,但又没有进行赋值的时候,C 会产生一些随机的值,有可能是先前的程序用过的;所以声明变量之后最好进行赋值

交换函数
#include<stdio.h>

void swap(int a, int b)int main()
{
    int x = 1;
    int y = 2;

    printf("x is %i, y is %i\n", x, y);
    swap(x, y);
    printf("x is %i, y is %i\n", x, y);
}

void swap(int a, int b)
{
    int tmp = a;
    a = b;
    b = tmp;
}

1702289590657

这个版本的代码为什么无法成功交换?

1702289697400

1702289928498

修改代码如下:

#include<stdio.h>

void swap(int *a, int *b);

int main()
{
    int x = 1;
    int y = 2;

    printf("x is %i, y is %i\n", x, y);

    // 需要传入的也是内存地址,而不是相应的值
    swap(&x, &y);

    printf("x is %i, y is %i\n", x, y);
}

// 接受的参数是内存地址
void swap(int *a, int *b)
{
    // 这里 *a *b 的值
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

溢出
  • A heap overflow is when you overflow the heap, touching areas of memory you are not supposed to.
  • A stack overflow is when too many functions are called, overflowing the amount of memory available.
  • Both of these are considered buffer overflows.
输入函数

get_int:

#include<stdio.h>

int main()
{
    int x;
    printf("x: ");
    scanf("%i", &x);
    printf("x:%i\n", x);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值