https://www.bilibili.com/video/BV1bo4y1Z7xf
https://gist.github.com/LittleBlacklb/ef27515ad9aeae13f956d6c5f302a4d5
There must be some grammatical errors here, please forgive me :(
<data type> *<variable name>;: The pointer to the <data type> of <variable name>
&<variable>: Return the address of the variable
*<variable>: Return the value at variable's address To access the address of the variable in format
The asterisk meaning between int* p and *p are not the same.
int* is a type that a pointer point to a data of int type.
*p is to dereference the address which stored in variable p.
int a = 1024;
int *p;
p = &a; // Assume variable `a` 's address is 2077
cout << p << endl; // 2077 in decimal
cout << p + 1 << endl; // 2081 in decimalint a = 1025;
int* p;
p = &a;
printf("Address=%d; value=%d\n", p, *p);
char* p0; // 1 char: 1 byte = 8 bit
p0 = (char*)&a; // Cast int* to char*
// 1025 in memory (small-endian order):
// ... 00000000 00000000 00000100 00000001 ...
// ...(p + 3) ^ (p + 2) ^ (p + 1) ^ (p + 0) ^ ...
// '^' means toward bit
printf("%d\n", (int)*p0); // 0000100 => 1
printf("%d\n", (int)*(p0 + 1)); // 00000001 => 4void* <variable name>;
It can't be used to print the value that it points.
It can be used to print itself address.
char c[] = "ABC";: It will be stored in the space for array (Stack).
const char* c = "Hello";: It will be stored as compile time constant, so it cannot be modified (Like: c[0] = 'a')
The relationship between Array & Pointer.
arr[x]<==>*(arr+x)(You need to know that
arris a const variable, so it cannot be assigned (Like:arr = var)It just the same as the relationship between Reference & Pointer
int &a = var<==>int* const a = &var
return a<==>return *a
// ...
int get_size(int arr[])
{
return sizeof(arr) / sizeof(arr[0])
}Most of the time, return result is 1 (Depend on the platfrom)
Because the declaration of
int arr[]is actually a int pointer which points to the first address of the array.Compiler translates
int arr[]=>int* arrSo the variable of
arr's size is the size of pointer.The purpose is to reduce the time and space cost.(It don't need to copy the array)
2-dimensional array:
a[i][j]=>*(a[i]+j)=>*(*(a+i)+j)
a's type:int (*)[]
a[i]'s type:int*
3-dimensional array:
a[i][j][k]=>*(a[i][j] + k)=>*(*(a[i] + j ) + k )=>*(*(*(a + i) + j ) + k
a's type:int(*)[][]
a[i]'s type:int(*)[]
a[i][j]'s type:int*
Yes! They are not the same type. You can't consider them as the same type!
int arr[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int (*p)[3] = arr;
printf("%d\n", p);
printf("%d\n", *p);This circumstance only happens in static creation!
p and *p's output are both equal
Differences:
p: It's a one-dimensional pointer;
*p: It's a int* pointer.
type of array inequals to pointer
In the other word, array is a special pointer.
-
It's a fake-pointer (pointer's address = the address it's point to) Because the static array is continuous. But dynamic multi-dimension array is not continuous from row to row.
-
It needs each row's capacity. For example:
sizeof(int[3]) = 12As we all know,sizeof(int) * 3 = 12 bytesSo when you do operator like+, C can know plus 1 equal to how many bytes
Static:
int arr[3][3];
for (int y = 0; y < 3; y++)
{
for (int x = 0; x < 3; x++)
{
// These following three are all equivalent
*(arr[y]+x) = 3 * y + x;
*(*(arr + y) + x) = 3 * y + x;
*((*arr + 3 * y) + x) = 3 * y + x; // Important!
}
}
int (*p)[3] = arr;
// All equal
printf("%d\n", p);
printf("%d\n", *p);int b[3][1];
int (*p)[1] = b;
// int **p = b; // Syntax ErrorDynamic:
int **arr = (int **)calloc(3, sizeof(int *));
for (int y = 0; y < 3; y++)
{
*(arr + y) = (int *)calloc(3, sizeof(int));
for (int x = 0; x < 3; x++)
{
// ...
}
}
int** p = arr;
// Not equal
printf("%d\n", p);
printf("%d\n", *p);It doesn't need [] type for helping.
Because it's structure is different from static array.
It's discontinuous, and is similar to deque in STL:
一段一段的连续空间's beginning address are different.
注意高字节在左边,低字节在右边
1 1 1 1
High Bit Low Bit
0b1001111
Big Endian
Low address in mem -------------> High address in mem
1 0 0 1 1 1 1
High Bit <----------------------- Low Bit
Small Endian
Low address in mem -------------> High address in mem
1 1 1 1 0 0 1
Low Bit <------------------------ High Bit
0b10010101
The bold underlined bit above called Least Significant Bit In Big-Endian order, LSB refers to the rightest bit.
-
代码区:存放函数体的二进制代码,由操作系统进行管理的
-
全局区:存放 全局变量 和 静态变量 以及常量
-
栈区:由编译器自动分配释放, 存放函数的参数值,局部变量等
-
堆区:由**程序员分配和释放**,若程序员不释放,程序结束时由操作系统回收
C:
Functions:
void *malloc(size_t size) void *calloc(size_t nitems, size_t size)` void *realloc(void *ptr, size_t size) void free(void *ptr)
C++:
Key Words:
new <variable>delete <variable>delete[] <variable>
Signature:
void *malloc(size_t size)
size_t: Positive number. The exact data type depend on the platform (unsigned int, etc.)
Usage:
int* p = (int*)malloc(4 * sizeof(int))
Replacing
sizeof(int)with4is not recommanded. Because the space of a data type depends on the compiler(platform)Malloc function return a generic pointer (
void*), so we need to do a type casting.
Signature:
void *calloc(size_t nitems, size_t size)`
size_t nitems: Numbers of elements of specific data type
Difference:
-
It can be more convenient to allocate a continuous memory.
-
It will initialize the allocated memory with
0.
Signature:
void *realloc(void *ptr, size_t size)
Application Scenarios:
- The new memory block may bigger than the original one.
- The function will mallocate a new memory block & copy the original data to there.
- If the old memory block's adjacency is available to use, the function will expand the old memory block.
- The new memory block may less than the original one.
- The function will free the unnecessary memory block.
//...
int n;
printf("Enter the size of array:\n");
scanf("%d", &n);
int *arr = (int*)calloc(n, sizeof(int)); // Dynamically allocated array
// arr = {0, 0, 0, ...} (n>3)
// ...
free(arr);Some machine or compiler may allows program to r/w memory block that freed. But sometimes may get crash.
// ...
realloc(NULL, n*sizeof(int)); // equivalent to malloc;
realloc(arr, 0); // equivalent to free;In C or C++:
int* p;
p = (int*)alloc(sizeof(int));
*p = 0x400;
free(p)In C++:
int* p;
p = new int;
*p = 0x400;
delete p;When you alloc a continuous space, you can use the space as a array.
In C or C++:
// ...
int* p;
const int SIZE = 4;
p = (int*)alloc(SIZE * sizeof(int)) // Allocate a 16 byte continuous space
for (int i=0; i<4; i++, p++)
{
// p[i] = i;
*p = i;
}
free(p)In C++:
int* p;
const int SIZE = 4;
p = new int[4]; // Allocate a 16 byte continuous space
for (int i=0; i<4; i++, p++)
{
// p[i] = i;
*p = i;
}
delete[] p;Normal:
//...
void func()
{
printf("void func(): called")
char chars = "1145141919810"; // 13 bytes
}
int main()
{
for (int i = 0; i < 100; i++) func();
return 0;
}The program's usage of the memory won't be raised up after finish calling the func()
Memory Leak:
//...
void func()
{
printf("void func(): called")
char* chars = (char*)calloc(1145, sizeof(char)); // 1145 bytes
// char* chars = new char[1145];
}
int main()
{
for (int i = 0; i < 100; i++) func();
return 0;
}The program's usage of the memory will be raised up after finish calling the func()
Reason: The allocated memory block in heap isn't deallocated after use.
Solution: Add a
free(chars)ordelete[] charsat the end line of the func()
In Java, C#, etc. The problem can't be happened, because they have their own garbage collection mechanism.
//...
int f1(int a) {/* ... */}
int f2(int* a) {/* ... */}
int main() {f1();f2();return 0}Concept:
int main();: In C/C++ called Calling function
int f1(int a);andint f2(int* a): Call Called function
int f1(var);: Call Call by value
int f1(*var);: Call Call by reference
The correct operation of returning pointer from function:
int* rtnAPointer()
{
int* p = (int*)malloc(sizeof(int));
*p = 0x1bf52;
return p;
}
int main()
{
int* p = rtnAPointer();
*p += 1919810;
printf("%d\n", p);
free(p);
return 0;
}A pointer which stores a function entry address.
Initialization syntax: <return type> (*<pointer name>)(<type>, ...);
Example:
void (*fp)(int, char);
Counterexample:
int *fp();
This declare a function that return int*, not a function pointer.
Call syntax: *(<pointer name>)(<type>, ...) or <pointer name>(<type>, ...)
Example:
*(f)(0x1bf52, 33);
f(0x1bf52, 33);
Why these two syntax are both correct?
You can compare this with array's syntax:
int arr[]<==>int* arr
*(f)()<==>f()
// ...
void f0() {printf("f0() called");}
void f1(void (*func)()) {func();}
int main() {
f1(f0);
return 0;
}What's the meaning of the callbacks?
In C library function, qsort use it.
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))
base − This is the pointer to the first element of the array to be sorted.
nitems − This is the number of elements in the array pointed by base.
size − This is the size in bytes of each element in the array.
compar − This is the function that compares two elements.
The reference example from:
#include <stdio.h>
#include <stdlib.h>
int values[] = { 88, 56, 100, 2, 25 };
int cmpfunc (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int main()
{
int n;
printf("排序之前的列表:\n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
qsort(values, 5, sizeof(int), cmpfunc);
printf("\n排序之后的列表:\n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
return 0;
}- Memory is byte addressable
- Memory is an array of bytes
- Each byte has a memory address
- Smallest data that can be addressed is a byte
- The reason that why boolean data type is 1 byte.
- Each address has 32 bits (ARM Cortex-M)
- The value of a pointer is simply the memory address of some variable
- If a variable occupies multiple bytes in memory, its address is the lowest address of all bytes it occupies.
The pink address is this integer's This is small-endian order
/*
* @Date: 2022-07-21 22:39:45
* @LastEditors: littleblackLB
* @LastEditTime: 2022-07-22 00:16:55
* @FilePath: \Cpp\src\Test.cpp
*/
#include <iostream>
using namespace std;
// 一个指针数组,拥有三个元素,每个元素指向一个函数原型为 void func()
typedef void (*(ARR[3]))();
// 一个函数指针返回一个数组,这是一个指针数组,容量为10,
// 每个元素指向一个函数原型为 void func()
typedef ARR *(*FUNC)(); // 等价于 typedef void(*(*(*FUNC)())[3])();
void func2()
{
printf("%d\n", 888);
}
void func3()
{
printf("%d\n", 889);
}
void func4()
{
printf("%d\n", 890);
}
ARR *func1()
{
ARR *rtn = new ARR[3];
// 解引用rtn指针到数组头指针,解数组头指针,并赋值为func2
**rtn = func2; // 等价于*rtn[0] = func2;
*rtn[1] = func3;
*rtn[2] = func4;
return rtn;
}
int main(int argc, char const *argv[])
{
system("chcp 65001");
FUNC f = func1;
ARR *fs = (*f)(); // 等价于ARR *fs = f();
for (int i = 0; i < 3; i++)
{
(*fs[i])(); // 等价于fs[i]();
}
delete[] fs;
system("pause");
return 0;
}





