<基类型>*<指针变量>
:void*
:可以作为所有指针的接口,void的指针类型可以被赋值为任何类型的指针。int a = 9;
int* p = &a;
int* q = p;//指向同一地址
*p = 8;
void* p1 = p;
double* q1;
p1 = q1;//是允许的
typedef int* Pointer;
// p和q均为指针变量
Pointer p, q;
//等价于
int*p, q;//主要q是int不是指针
int *p = (int *)0x080483A0;
int *p = 0x080483A0;
&
*
int x=9;
int *p;
p = &x;
*p = 1000;
char *p = (void*)
nullptr
:作为不依赖任何值的指针。Pointer p = nullptr;
//ANSI C
#define NULL ((void*)0)
//C++
#define NULL 0
//以下的情况,会调用int的重载版本
void func(int);
void func(char*);
func(NULL);
p = &d//error,不同类型
int* p ;
double *q;
//注意这里的++隐含的意义是加上一个sizeof(type)
p++;//p的值加4 (sizeof(int))
q++;//q的值加8 (sizeof(double))
int a[10] = { 1,2,3,4,5,6,7,8,9,10 };
int *p = &a[0];
for (int i = 0; i < 10; i++) {
cout << *p++ << " ";//指针移动
cout << *p << " ";
cout << *(p + i) << endl;//指针不动
for (int j = 0; j < 10; j++) {
cout << a[j] << " ";
}
cout << endl;
}
int x=1;
int *p=&x;
cout << p; // p的值 (x的地址)
cout << *p; // p所指向元素的值
char *p = "ABCD";//有问题
char *p = (char *) "ABCD"//没有问题,但是并不推荐这么使用
cout << p;//p指向的字符串,即: ABCD
//调用ostream& operator << (ostream&, char*)
//调用时,operator << (cout,p);
cout << *p; //p指向的字符,即:A
cout << (int *)p //p的值
void *p;
void *any_pointer;
int x;
double y;
any_pointer = &x;
any_pointer = &y;
*any_pointer //error,对void*类型的指针取值的时候,一定要先转换为对应具体类型的指针后再进行取值
*((int *)any_pointer) //OK
*((double *)any_pointer) //OK
//例:将某块内存清零,按照bit进行处理!
void memset ( void *pointer, unsigned size) {
char *p = (char *)pointer;
for (int k=0;k
memset(void *s,int ch,size_t n);
struct A{...};
A a;
memset(&a,sizeof(A));
int A[100];
memset(&a[0],100);
int arr[100] = {0};
memset(arr,sizeof(arr));
memset(arr,100 * sizeof(int));//arr作为参数传递时
const <类型> * <指针变量>
const int c = 0;
const int *cp;
int y = 1;
int *q;
cp = &c; √//cp 可以指向 c
q = &y; √//q 可以指向 y
*cp = 1 ; ×//*cp 是一个常量,不可以赋值
*q = 2 ; √//变量指针可以指向变量
cp = &y; √//常量指针可以指向变量,传递的是y的空间,并且对于y的这个空间只是可读的,安全的
q = &c; ×//不可以的,因为q的修改可以间接修改c,所以编译器不允许
void print(int *p){
cout << *p << endl;
}
const int c = 8;
print(c) ;//不可以被调用的
print(&c);//C++赋给的权利,在调用的时候除去常量的特性,这个&是强制类型转换,取消常量特性
void print(const int *p){//如此修改就可以大量复用
//常量使用者和变量使用者都可以使用
cout << *p << endl;
}
void Fun1(int *p){
//*p 读写
}
void Func2(const int *p){
//*p 只读
}
int x=10;
int *p = &x;
cout << " x " << &x << x << endl;
cout << " p " << &p << p << endl;
cout << "*p " << p << *p << endl;//*p = x
//Name Addr Value
//x 0012FF7C 10
//p 0012FF78 0012FF7C
//*p 0012FF7C 10
const int c = 128;
int * q = const_cast(&c);//强制类型转换
*q = 111;//企图通过变量指针修改常量
cout << " c " << &c << c << endl;
//这里的c是符号常量,所以在编译的时候,符号常量已经变为128了,相当于define
cout << " q " << &q << q << endl;
cout << "*q " << q << *q << endl;
//Name Addr Value
//c 0012FF74 128
//q 0012FF70 0012FF74
//*q 0012FF74 111
//why?为什么这个单元对于c是128,而对于q这个单元是111,见上面,确实已经修改成111了
void showBytes(void *q, int n)//查看内存
{
cout << n << endl;
unsigned char *p = (unsigned char *)q;
for (int i=0; i
<类型>* const<指针变量>
int x,y;
int *const p = &x;//p就始终如一的指向x这个单元
//同时这个单元是可变的
p = &y;//错误的
int A[2];
typedef int T[2];//相当于int[2] T
double (*fp)(int);//fp是指向函数的指针
double (int) * fp;//上面的理解,不能这么写
double *fp (int);//符合C++语法,fp是一个函数,参数是int,返回值是double*
typedef double (*FP)(int);
typedef double (*)(int) FP;//上面那个的理解
double f(int x){}
int g(){}
void main(){
FP fp;
fp = f; //相当于fp = &f;为函数指针赋值
(*fp)(10);//相当于fp(10);
fp = g; //Error
}
#include
using namespace std;
int add(int a,int b) {return a+b;}
int minus(int a,int b) { return a-b; }
void main(){
char c;
int op1, op2;
cin >> c;
while (c != '#'){//#是终止符
//类似Windows中的一些时间的参数
//以下对应getTask()
cin >> op1;
cin >> op2;
//以下对应executeTask()
switch (c){
case '+': cout << add(op1,op2) << endl;
break;
case '-': cout << minus(op1,op2) << endl;
break;
}
cin >> c;
}
}
//剥离IO getMessage,和操作系统一样
struct Task{
int op1;
int op2;
OPRAND_TYPE op;
};
enum OPRAND_TYPE { END=-1, ADD, MINUS};
int add(int a,int b) { return a+b; }
int minus(int a,int b) { return a-b; }
//add 和 minus 抽象成函数指针
typedef int (*FP)(int, int);
OPRAND_TYPE getTask(Task &task){
char c;
cin >> c;
switch (c){
case '#':
task.op = END;
break;
case '+':
task.op = ADD;
cin >> task.op1;
cin >> task.op2;
break;
case '-':
task.op = MINUS;
cin >> task.op1;
cin >> task.op2;
break;
}
return task.op;
}
//抽离计算部分第一版
//如何修改可以使得无论多少个任务都不导致如下方法的修改
void executeTask(const Task task){
FP fp;
switch(task.op){
case ADD: fp = app;break;
case MINUS : fp = minus;break;
}
fp(task.op1,task.op2)
}
//抽离计算部分第二版代码
//Table Driven
FP op[2] = {add, minus};
void executeTask(const Task task){
op[task.op](task.op1,task.op2);
}
void main()
{
Task task;
while (getTask(task) != END)
executeTask(task);//call by reference
}
//组织改善:利用define,集合IDE
//完成时间处理、协议解析、服务框架
//第一版实现冒泡排序,默认数据类型为int
void MySort(int A[],unsigned int num)
{
for (unsigned i=1;i A[j+1]){
int tmp = A[j];
A[j] = A[j+1];
A[j+1] = tmp;
}
}
}
void MySort(void *base, unsigned width,unsigned num,int(*compare)(const void *elem1,const void *elem2)){//这部分意味着我们必须要传入一个compare的函数
char *A = (char*) base;//void* 是不可以进行移动的
char *tmp = (char*)malloc(width);//申请堆空间
for (unsigned i=1;i 0){//序关系由函数确定
memcpy(tmp,A + j * width,width);//tmp = A[j]
memcpy(A + j * width,A+(j+1)*width,width);//A[j] = A[j+1]
memcpy(A + (j + 1) * width,tmp,width);//A[j + 1] = tmp
}
}
free(tmp);//释放这部分的空间
}
struct TStudent
{ char name[20];
int age;
};
TStudent student[] = {...};
int num = sizeof(student)/sizeof(student[0]);//计算出来有多少个
int width = sizeof(student[0]);//计算出来宽度
MySort(student, width, num, icompare);
MySort(student, width, num, scompare);
//compare不用给大小,因为compare是调用者给出的,显然不用给出width了
//call back function:在运行中反过来调用
int icompare(const void *elem1, const void *elem2){
TStudent *p1 = (TStudent *)elem1;
TStudent *p2 = (TStudent *)elem2;
return p1->age - p2->age;
}
int scompare(const void *elem1, const void *elem2){
TStudent *p1 = (TStudent *)elem1;
TStudent *p2 = (TStudent *)elem2;
return strcmp(p1->name, p2->name);
}
template
void MySort(T A[],unsigned T num)
{
for (unsigned i=1;i A[j+1]){
T tmp = A[j];
A[j] = A[j+1];
A[j+1] = tmp;
}
}
}
int a[100];
sort(a,100);//此时的T转换成为int(对应类型)
class C{...}
C a[300];
sort(a,300);//编译器可以将其变为C,但是有问题
//我们需要重载>运算符
直接给出即可
#include
double integrate(double (*f)(double),double a, double b)
{ … f(x), a , b, … }
double my_func(double x){ … }
void main(){
integrate(sin,0,1);
integrate(cos,1,2);
integrate(my_func,1,10);
}
*(p+i)
:p不移动*(p++)
:p移动int *p = a
:这时候a表示的是数组的首地址
int * const
void f(int A[],int n){
sizeof(A)/sizeof(A[0])//始终1,就是地址
}
sizeof(a)
:是数组的整个块的大小sizeof(a[0])
:是数组中一个元素的大小int *p = &a[0][0]
:p指向的是T类型for(int i = 0;i < 12;i++){
*(p++) = 9;//越界了(对应一维数组的越界),但是二维数组没有越界
}
typedef int T[2];
T a[6];//int a[6][2]
T *q = a;
//不使用T的方法
int[2] *q;
int a[10];
sizeof(a);//数组大小
sizeof(a+1);//内存地址的长度,单位bytes
int *p;
int i=0;
p = &a[0] == p = a;
a[i] == *(a+i) == *(p+i) == p[i]
&a[i] == a+i == p+i == &p[i]
int b[20][10];
//等价于
//typedef int T[10];
//T b[20];
int *q;
q = &b[0][0];// q = b[0]
//b[i][j] == *(&b[0][0] + i*10 + j) == *(q + i * 10 + j) == q[i*10 + j]
T * p;//int (*p)[10];
p = &b[0];// p = b
//b[i][j] == *(*(b+i)+j) == *(*(p+i)+j) == p[i][j]
#include
int maximum(int a[], int n)
{
int max = 0;
for(int k=0;k max)
max = a[k];
return max;
}
void main()
{
int A[2][4] = { {68,69,70,71} , {85,86,87,89}};
cout << "the max grade is" << maximum(A[0],2*4);//maximum(&A[0][0],2*4) =>maximum(&A[0][0],sizeof(A)/sizeof(A[0][0]))
}
void show(int a[], int n){
for (int i=0;i
main函数:int main(int argc,char * argv[],char * env[])
Eg.
ping -t 192.168.0.1
argc : 3
argv: ping / -t / 192.168.0.1
env:
char *s1[] = {"C++", "PASCAL", "FORTRAN"};
char s2[][8] = {"C++", "PASCAL", "FORTRAN"};
int printf(const char*,...)
:后面是可变参数,由调用者决定。const char*
:是调用者和被调用者之间的约定目标求Q
X = Qn + r, -n < r <= 0 Q大于X,能放下,并且是整数倍
思考:X = qn + r, 0 <= r < n
q = x/n
r = x%n
这样子就能求了
X + n - 1 = Qn + r1, 0 <= r1 < n
Qn = ((x + n - 1)/ n) * n
n 是 2 的幂次 => 左移右移都是乘以或者除以2
n = 2 的 m 次方
所以先乘以2再除以2,相当于后m为全部清0
也就等价于(x+n-1) & (~(n-1))
//platform : x86 宏的说明,这不是在库文件中已经定义了的
typedef char *va_list;
#define _INTSIZEOF(x) ((sizeof(x) + sizeof(int) - 1) & ~(sizeof(int) - 1)) //alignment 偏移的大小
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
#define va_end(ap) ( ap = (va_list)0)
#include
#include
using namespace std;
void MyPrint(char *s, ...){
va_list marker;//拿到一个指针
va_start(marker,s);//找到参数的位置,s的位置
int i=0;
char c;
while ((c=s[i]) != '\0'){
if (c != '%')
cout << c;
else{
i++;
switch (c=s[i]){
case 'f': cout << va_arg(marker,double); break;
case 'd': cout << va_arg(marker,int);break;
case 'c': cout << va_arg(marker,char);break;
}
}
i++;
}
cout << endl;
va_end(marker);//将当前指针回归原始状态
}
int max(int num, ...) {
va_list marker;//拿到一个指针
va_start(marker, num);
int maxNum = 0;
int tmp = 0;
for (int i = 0; i < num; i++) {
tmp = va_arg(marker, int);
if (tmp > maxNum) {
maxNum = tmp;
}
}
va_end(marker);//将当前指针回归原始状态
return maxNum;
}
void main(){
MyPrint("double: %f integer: %d string: %c ",1.1, 100, 'A');
cout << max(5,10,20,50,30,40);
}
(*p).x == p->x
void myswap(int *p1, int *p2) {
int* tmp = p1;
p1 = p2;
p2 = tmp;
}
void myswap2(int &p1, int & p2) {
int tmp = p1;
p1 = p2;
p2 = tmp;
}
void myswap(char **p1, char **p2) {
char *tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
void main()
{
char *p1 =(char*) "abcd";
char *p2 =(char*) "1234";
int a = 100;
int b = 200;
myswap(&a, &b);
cout << a << " " << b << endl;//100 200
myswap2(a, b);
cout << a << " " << b << endl;//200 100
myswap(&p1, &p2);
cout << p1 << " " << p2 << endl;//1234 abcd
}
new <类型名> [<整型表达式>]
//--------------------------------------
int x;
int *p = new int;
delete p;
int *p = (int *)malloc(sizeof(int));
free(p);
int &a = p;
//malloc
void * malloc (unsigned int size)
p = (int *)malloc(sizeof(int)); //new int
q = (int *)malloc(sizeof(int)*20); //new int [20]
//---------------------------------------
int *p = new int[10];//分配一块连续空间
int *p = (int*)malloc(sizeof(int)*10)
int (*p2)[5] = (int (*)[5])p;
for (int i=0;i<10;i++)
p[i] = i+1;
q = new int[2][5];//错误的,没有这种写法
//想用二维数组访问,升维操作
for (int j=0;j<2;j++)
{ for (int k=0;k<5;k++)
cout << p2[j][k] << " ";
cout << endl;
}
//---------------------------------------
//多维数组使用构造数据类型申请内存
typedef int i5Array [5];
void main(){
i5Array *p = new i5Array [2];
for (int j=0;j<2;j++)
for (int k=0;k<5;k++)
p[j][k] = (j*5)+(k+1);
}
//---------------------------------------
class A
A *p = new A;//调用默认构造函数
A *p = (A*) malloc(sizeof(A));//只是分配空间
//---------------------------------------
namespace std{//处理内存
typedef void (*new_handler)();
new_handler set_new_handler(new_handler p) throw();
}//不满意应对,我们可以重载方法来处理
new -- delete|delete[]
malloc -- free
int *p = new int[8];
for(int i = 0;i < 8; i ++){
*(p++) = 128;
}
delete[] p;
//很大的问题,因为p移动过,这时候指针想上看size:128,就向下归还128个字节。
struct NODE{
int content;
NODE *next;
};
NODE *head=NULL;//使用头结点
//节点初始化
NODE *p = new NODE;
p->content = _value;
p->next = NULL;
head是不可以动的
//链表为空
head = p;
//链表不为空
p->next = head;
head = p;
//表尾插入
NODE *q = head;
while (q->next != NULL)//从头结点找到尾结点
q = q->next;
q->next = p;
NODE *q = head;
while (q != NULL && q->content != a ){
q = q->next;
}
if (q != NULL){
//存在a
p->next = q->next;
q->next = p;
}else{
//不存在a
cout << "Not found!";
}
//插在链表中某结点(值为a)的前面
NODE *q1=NULL, *q2=head;//q1是q2的前一个结点
while(q2 !=NULL && q2->content != a){
q1 = q2;
q2 = q2->next;
}
if (q2 != NULL){//存在a
if(q1 == NULL){// a是第一个结点
p->next = q2;
head = p;
}else{// a不是第一个结点
p->next = q2;
q1->next = p;
}
}else{//不存在a
cout << "Not found!";
}
NODE *q1=NULL, *q2=head;//q1是q2前面的一个结点
while (q2 != NULL && q2->content != a){
q1 = q2;
q2 = q2->next;
}
if (q2 != NULL) {//存在a
if (q1 == NULL){
// a是第一个结点
head = q2->next;
delete q2;
}else{// a不是第一个结点
q1->next = q2->next;
delete q2;
}
}else{
//不存在a
cout << "Not found!";
}
struct Node{
int k;
Node *next;
} *first = NULL;
void release(){
//释放整个单向排序链
while(first != NULL){
Node *p = first;
first = first->next;
delete p;
}
}
void print(){
//打印整个单向排序链
Node *p = first;
while (p){
cout << p->k << endl;
p = p->next;
}
}
insert(Node *first, int n);
void insert(int k){
Node *p = new Node;
p->k = k;
p->next = NULL;
//创建新结点
if (!first){
//链表为空
first = p;
}else if (k < first->k){
//插入在头结点
p->next = first;
first = p;
}else{
//插入在后面
Node *p1 = first;
while (p1->next != NULL && k > p1->next->k)
p1 = p1->next;
p->next = p1->next;
p1->next = p;
}
}
//first作为main里面的局部变量,如下使用会有问题吗
void main(){
Node* first = NULL;
insert(first,n);//有问题,值传递,不能修改first
insert(&first,n);//这样子就行了
}
void delNode(int k){
if (!first) return;
Node *p1 = first;
if (k == first->k){
//删除头结点
first = first->next;
delete p1;
}//删除头结点
else{
while(p1->next != NULL&& p1->next->k != k)
p1 = p1->next;
if (p1->next != NULL){
Node *p = p1->next;
p1->next = p->next;
delete p;
}
}
}
int &a = *p;//一旦是p的别名,就一定只能是p的别名了
void f(int &a)//利用函数副作用
int max1(int x[], int num){
int m,i;
m = x[0];
for (i=1; i m) m = x[i];
return m;
}
int &max3(int x[], int num){
int i, j;
j = 0;
for (i=1; i x[j]) j = i;
return x[j];
}
int *max2(int x[], int num){
//返回的指针
int *p,*q;
p = x;
q = x+1;
while (num > 1){
if (*q > *p) p = q;
q++; num--;
}
return p;
}
int main(){
int A[16];//操作的是调用者的空间的部分
cout << max1(A,16);
cout << max2(A,16);//返回的是一个地址
*max2(A,16) = -1;//将最大值修改为-1
cout << max3(A,16);
max(A,16) = -1;//将最大值修改为-1
}
void swap(const int& a, const int& b)
int *p = new int(100);
int &x = *p; …… ;
delete &x;