哈佛大学公开课:计算机科学cs50 学习笔记(第10集:指针,内存)

1. 复习RAM

text 部分存储编译后的二进制文件,如源代码。initialized data 和 uninitialized data 分别存储初始化和未初始化的全局变量; heap 负责动态内存分配的内存(如 malloc()函数) 自上而下增长; stack负责存储函数调用,包括局部变量,参数,函数地址以便函数调用结束后还能回到原来调用它的函数继续运行,自下而上增长。

2. 指针

void swap(int a, int b)
{
	int temp = a;
	a = b;
	b = temp;
	printf("a=%i\n", a);
	printf("b=%i\n", b);
}

以上这个swap函数不能起到交换变量的作用。原因:https://blog.csdn.net/shaozhenghan/article/details/81256477

使用指针即可:

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

传指针形参。

swap函数执行完后,它对应的stack 被 “清除”,即计算机忘记了stack局部变量和参数的存在。但它们确实依然存在。

指针存储一个变量的地址,指针本身所占内存总是一样大,32位或者64位,不管它指向什么类型,char 或者 int

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

int 
main(int argc, char **argv)
{
    char * s1 = argv[1];
    printf("%s\n", s1);
    char * s2;
    s2 = s1;
    // *s2 = "mmm";
    s2[0] = 'm';
    printf("%s\n", s1);
    printf("%s\n", s2);
    return 0;
}

这段代码,s2 = s1 并不是拷贝!而是因为s1 是指针,指向argv[1]这个字符串的首元素,即char类型。s2 = s1 是将s1存储的地址复制给了s2, 所以s2 也指向 argv[1]的首元素。所以更改s2[0]也同样会对s1[0]改变。

例如:

注意:下面这样的赋值是错的。因为*s2 的类型是整型,而“mmm”是一个指针!

会报错:

warning: assignment makes integer from pointer without a cast [-Wint-conversion]

*s2 = "mmm";

因为s1 未知大小,所以要拷贝,应该用动态内存分配:

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

int 
main(int argc, char **argv)
{
    char * s1 = argv[1];
    printf("%s\n", s1);
    printf("%i\n", (int)strlen(s1));

    char * s2 = malloc((strlen(s1)+1) * sizeof(char));
    printf("%i\n", (int)strlen(s2));
    
    unsigned int n = (int)strlen(s1)+1;
    for(unsigned int i = 0; i < n; ++i)
    {
        s2[i] = s1[i];
    }
    s2[n] = '\0';

    s2[0] = 'x';

    printf("%s\n", s1);
    printf("%s\n", s2);

    return 0;
}

其中下面这句很关键。如果没有给s2 分配内存,就试图访问s2,会有segmentation error!

若没有给s2 分配内存,s2 默认为 NULL 也就是 0, 0x00

char * s2 = malloc((strlen(s1)+1) * sizeof(char));

malloc()函数在RAM 的堆heap里面,分配一块指定大小的内存,返回值是这个内存的首地址!

返回的首地址存在s2里面,而s2 则是位于RAM的stack里面!

strlen(s1)+ 1 是因为s2要以‘\0’结束。

乘以sizeof(char)是方便跨平台,因为不同硬件平台上char的大小可能不一样。

运行结果:

可以看到这次是拷贝了。

再一个例子:

int * x;
int * y;

printf("%i\n", *x); // 错误!

int * x = malloc(sizeof(int));

*x = 22; // 正确!指针x已经分配内存了。

*y = 13; // 错误!segmentation error,因为指针y还没有分配内存

y = x;
*y = 13; // 正确。

猜你喜欢

转载自blog.csdn.net/shaozhenghan/article/details/81351187