# 进制和符号

16 进制前用 0x 表示,有 0123456789ABCDEF 16 位。

int n = 50;
printf("%p\n", &n);
// 表示打印 n 的地址

当你询问某个值的地址,你会获得指向该值的指针 (pointer, % p),& 表示获取 n 的地址,* 表示去一个特定的地址,因此 printf("%i", n)printf("%i", *&n) 输出是一样的。I’m getting the address and going to the address, there by defeating the point.

# 指针

int n = 50;
int *p = &n;
printf("%p\n", p);  // ---> 0x123
printf("%i\n", *p);  // ---> 50

要获得某物的地址,必须将其存储在指针中,不能存储为整数, int * 是一种新的数据类型。

string s = "EMMA" 中,string 应该说是错的,实际上在计算机内部是这样的:
string
5 bytes(字节)或者 40 bits(位),在多数现代计算机中,指针使用 64 bits 相当于 long 那么大的空间。

s 是指向内存中 EMMA 实际名字的指针, string s = "EMMA" 实际上应该是 char *s = "EMMA" ,* 表示地址,char 表示被指向的地址类型。 char * 意味着 值的类型 将是一个 字符的地址。


test-1
int main(void)
{
    char *s = "EMMA";
    prints("%s\n", s);  // ---> EMMA
    printf("%p\n", s);  // ---> 0X123
    printf("&p\n", &s[0]);  // ---> 0X123
}

5、6 行代码输出一样 证明了,当你 print out s(一个字符串),它仅仅是第一个字符的地址。

test-2
char *s = "EMMA";
printf("%c\n", *s);  // ---> E
printf("%c\n", s[1])// ---> M
printf("%c\n", *(s + 1));  // ---> M

这就是为什么上周我们说。你不能比较两个字符串,必须用 strcmp 比较每个字符,因为存储了两个 EMMA 中 E 的地址不同。

# 内存分配

通过 malloc 内存分配,它可以记住起始地址,() 填字节数。

malloc example
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
    char *s = get_string("s: ");
    char *t = malloc(strlen(s) + 1);
    for (int i = 0, n = strlen(s); i < n + 1; i++)
    {
        t[i] = s[i];
    }
    // for loop same as strcopy(t, s);
    t[0] = toupper(t[0]);
    printf("%s\n", s);
    printf("%s\n", t);
    free(t);
}

malloc 使用之后必须用 free 来释放内存,可以用 valgrind 来分析错误。

null
char *s;
printf("s: ");
scanf("%s", s);
// 不用 '&' 因为 s 就是指针或地址
printf("s: %s\n", s);

这是不行的。s 需要初始化一个地址,可以写 char *s = NULL ,null 表示没有其他指针的地址,也被称作空指针,但是空指针还没有分配内存。可以改成这样:

char s[5];
printf("s: ");
scanf("%s", s);
printf("s: %s\n", s);

An array is just a chuck of memory back-to-back-to-back.
A string is just a sequence of characters back-to-back-to-back.

# 交换数据

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

实际上这样做并不能生效。swap 交换数据,实际上并没有交换 xy 只是拷贝了 xy —> ab,然后交换 ab,之后退出,a b tmp 都没了,xy 仍然是 xy。应该这样做:

swap

内存中情况是这样的:

memory

  • stack overflow 堆栈溢出,函数重复调用自己
  • heap overflow 堆溢出,一直调用 malloc,要了太多内存,却没有 free。
get_function
int x;
printf("x: ");
scanf("%i", &x);
printf("x: %i\n", x);

将数字存储在 x 的地址,传递给 x 地址的原因与 swap 问题相同,如果要使用辅助类的函数,希望它更改变量的值,你无法通过值来传递它,不能只传递 x,因为它将获得一个副本,函数退出后社么也不会发生。必须用 & 来传递 x 的地址,函数(scanf or swap)可以转到该地址进行操作。

# 识别 jpeg

Jpeg

# 文件读写

还是电话本项目

phonebook
int main(void)
{
    FILE *file = fopen("phonebook.csv", "a")
    // 第一个参数是文件名,第二个参数是 r/w/a
    
    char *name = get_string("Name: ");
    char *number = get_string("Number: ");
    fprintf(file, "%s,%s\n", name, number);
    fclose(file);
}
  • fopen: 将返回指向该文件的指针
  • fprinft: You can print literally to a file.
  • csv: comma separated valyes