
Pointer
Table of Contents
original video: https://www.youtube.com/watch?v=h-HBipu_1P0&list=PL2_aWCzGMAwLZp6LMUKI3cc7pgGsasm2_
Basic
dereferencing
*有不同的概念:
-
*p : 这个pointer指向的address里存的value
-
int *p; //定义一个指针
有时候有的人会写成
int* p 和 int *p 是一样的
问 address in p会指向b吗?
不会
generic type?
为什么不能用generic type, 而是要给 *p 也声明一个type呢?
we do not only use the point to store the address, but also use them to dereference these address, so we can access and modify the value in these address
这四个橙色的框是一个int的表示(因为int 是4byte, 一个byte含有4个bits)
signbit : 来存储这个数字是positive or negative(正还是负)
当我们dereference p的时候, 因为p是strong type, 所以他就知道我们要看4个位(start from 200), know how to extract an value from an integer type
we put the same address as we have in p to p0
p0 = p
, 但这个会报错? 为什么?
generic pointer type
这不是空指针,空指针指的是不指向具体地址(NULL)的指针, void强调的是无类型. 所以没有办法dereferencing(*p0),
也没有办法运算(p0+1 这种是不行的)
pointer to pointer
这里r里面应该为205
pointer use as function arguments
stack : 保存parameters, local variables, the calling function to which is should return(返回的地址)...
each function 都有一个 stack frame
首先执行main,遇到increment函数,main暂停, 在stack中开辟一块新的空间来执行increment, 当执行完, 清楚increment所在的stack frame, 也就意味着increment 从 stack中退出, 此时继续执行main
(注:下面这段代码我们期待输出11, 但输出10, 这是为什么呢?)
了解了为什么不是11的原理之后, 我们现在提出解决方法: 用pointer
pointers and arrays
其实可以直接写成 p = A, 都不需要写&符号
array as function arguments
按理来说 sizeof(A)应该是20, sizeof(A[0])是4(因为是int, 所以占四个bytes), 但为什么会输出1呢?
为什么?
当数组做formal argument的时候, 不会copy整个数组, 而是创建一个同名的pointer, 准确地说, 是A数组的首元素的地址传了过去
compiler 看这个int A[], 就是一个 int* A
character arrays and pointers
how to store Strings
我们把String当作参数传入, 假如array 的长度是8, string 存在 array里, 那怎么知道这个字符串到index几结束呢?
所以我们会添加一个标识'\0'
来表明,这个字符串到这里就结束了, 所以也解释了为什么 需要 字符串+1的空间来存储字符串
用下图这种方式定义, \0
是 implicit
这样的话是explicit, 意思也就是你必须自己把 \0
写出来
arrays and pointers use
arrays are always passed to function by reference
若字符串常量出现在在表达式中,代表的值为 该字符串常量的第一个字符的地址。
比如不可以写 C[0] = 'A', 会报错, 但是看下面
C是个地址,传给函数就是pointer
pointers and multi-dimensional arrays
1-D array
整型数组不是整型,整型数组里的元素是整型?
多维数组, 就是数组的数组
当仅使用数组名的时候, 它会返回数组首元素的pointer, B返回的不是一个整型指针, 所以不可以写int *p = B
我们可以看出, B是一个指向一维数组的指针(含3个int), 那 B+1也是一个指向一维数组的指针
B是二维数组的名字, B[0]是一个1-D数组, 不是数组里面的元素
B相当于二维数组首地址(一维数组),那一维数组的首地址就是首元素地址
二维数组(数组的数组),*代表解引用一层,从二维解到一维,再从一维解到值。所以 *B就是代表一维数组的地址?
直接输出C数组, 输出的是C数组第一个元素的地址
*C 输出的是 C 数组中第一个元素的值
*B 输出的是 B数组中第一个元素的值
而 B 是一个 2-D 数组, 所以第一个元素是个数组 B[0] , 输出这个数组.
那我们知道, 输出数组也就是输出它第一个元素(B [0] [0] )的地址
所以 *B会输出一个地址, 而 B+1 是指的是第二个数组, 所以同理
*(B+1) 输出的也是一个地址, 也就是第二个数组第一个元素的地址
B 和 *B都返回指针,
但是B返回一个指向一维数组的指针, *B 返回一个指向整形的指针
三维数组
c[0]指向的是一个一维数组,c才是指向二维数组
C[1]指向的是从816开始到831结束的一维数组,但是这个一维数组里面嵌套了两个二维数组C[1] [0]和C[1] [1]。但是C[1]指的是C[1] [0]的地址,然后指针运算+1
如果把三维数组传进function
stack and heap
首先看一下全局的application memory
在运行的过成功, 上面这三个区域是不会grow的
运行过程
main() -> total -> a,b
Sos() -> xyz
sq() => x
sq在运行的过程中paused, 等待sos 或者 main return一些数据来, 然后再继续执行, 当sq()这个方法return了, 就会从stack中被清除, 然后sos() 退出, 然后print方法加入进来
![]()
然后print方法再退出, mian finish 也退出, 然后total 也会被decleared
当program开始的时候, os会allocate一些空间给stack
the size of the stack-frame is calculated while compling, 如果占完了stack的空间, 那就是stackoverflow(比如你写了一些奇怪的recursion), 所以当我们申明一些大的变量, like array, 我们需要know the size at complie, 而不是running
在stack上面的先执行,其他的会暂停 , 执行完就退出, 当mian也执行完, global也退出了
给 large chunks of memory allocate空间 或者 保持变量在memory中 直到而我们需要的时候, 我们need Heap
heap大小是可变的, 也叫做free store, dynamic memory, 这里我们说的heap不是data structure里的heap, 我们这里只指large free pool of memory, 当我们需要的时候就可以用
用malloc方法,传入参数(4 bytes),就会在heap里创建一个内存空间, 不调用free, 这个10就会在heap里一直占内存
malloc方法会返回一个pointer, (也就是starting address of this block, 图上首先是200, 然后是400), 所以我们需要使用free方法
注: new出来的东西在heap里
下图是在heap里面存一个array(用的是C++了. 不是C)
malloc, calloc, realloc, free
这些函数, 适用于支持 dynamic memory allocation, 我没听这节
memory leak
improper use of dynamic memory of the heap section, 就是在堆上增长垃圾, (我们申请了内存, 但用完之后不释放它)
比如我每次调用方法, 都用malloc分配空间, 所以每次调用方法都有一个pointer指向heap里面的一部分空间,
所以方法一直调用的话, heap里面就堆满了垃圾,
但java和C#不会 ,堆上的垃圾会被自动回收, 这就是java 的垃圾回收机制
pointers as function returns
我的理解是mai函数中传过来的值a的地址值,所以Add函数中a的值为传过来的地址值,所以Add中的a的值等于main中的&a,但Add中的a的地址即&a则是其他值, 所以不一样
我们在顶部添加一个函数叫helloword之后(直接输出一句helloword), 结果add方法输出的sum出了问题, 这是为啥
现在add方法执行完了, 退出空间了
现在要执行helloword方法, 要为其分配内存空间, 那加入分配到130-135, 那岂不是原来add方法的空间, 现在144这个空间就不再存储6了
那也就意味着, 如果方法返回一个指针, 如果后面还需要执行其他方法, stack内存会被其它方法占用, 那么怎么办呢?
用malloc在heap上分配内存, 这样pointer就指向heap了
function pointers
用来store the address of functions
in memory, function is one continious block with some instrctions
function 的地址, 我们也把他称为函数的入口点, will be the address of the first instrcution
调用函数就是jump to 函数的第一条instruction
参数类型要和你要指向的函数的类型是一样的