1.内存按一个字节一个字节顺序编址,从0~4G
2.内存空间(内存编址)地址编号。
变量类型 变量名=变量值
3.(&变量名)什么意思?
答:取变量所在的地址编号。
printf("%d\n",i); //输出i的值
printf("%x%X%p\n",&i,&i,&i); //输出i的内存地址(用三种方式)
指针就是一个指向标,它可以告诉你想要去的地方的地址;就好似现实中的一个路标一样。指针变量所存的内容就是内存的地址编号!
内存地址→6 7 8 9 10 11 12 13 14 15
----------------------------------------------------------------------------------
??? | 30 | ‘t’ | 6 |...
----------------------------------------------------------------------------------
变量 |→i ←|→a ←|→ pi ←|
4.任意指针类型的变量在32位机器上都只占4字节(32位)内存空间。
那定义指针类型有什么用,是为了给指针赋值的时候两边的类型保持一致吗?
char c,*pc; // c,*pc两个变量地址分配是按顺序排列的吗?*号的作用是什么?定义指针时为什么要用*号?
5.a[i]=*(a+i),数组名不占内存,它只是一个符号标识。数组名不能被赋值,不能用来++,--。数组名只是一个指针常量。数组名代表整个数组的首地址。
6.int const *pi=&i;//const int *pi=&i; //常量指针(自以为指向常量的指针),不能通过*pi改变i的值,但是可以改变其指向的地址。只有const放在前面才说明pi是个常量指针。而int *const pj=&j; 只是说明pj的地址是个常量不能改变,可以通过*pj来改变j的值。
int *const pj=&j; //pj 是个指针常量,pi是个指针变量
const int *const pm=&i; //定义的是常量指针且pm为指针常量。指向的地址和值都不可改变
7.指针变量指向常量会出现警告. //一般情况下不允许这样的操作
8.存放在栈空间里的内容,程序执行完后了自动清除。
9.不知道它指向那里的指针为野指针。
例:int *p;
指针变量值为零的指针为空指针(零指针)
例:int *p=NULL;
void *p=NULL; //空类型指针(万能指针)可以指向任意类型的地址;
使用万能指针来打印它所指向的内容的时候需要加上强制类型转换,将其转换为与其打印内容相同的类型
10.**p //二级指针(指向指针的指针)
11.将某个变量的地址赋给一个指针变量,指针变量通过地址可以直接对该变量的内容的进行操作。
12.认识指针的步骤:变量的内存实现;指针是什么;指针与数组名;const int* pi/int* const pi的区别;函数参数的传递;指向另一指针的指针;函数名与函数指针。
13.指针本身是个变量,它所存储的是一个地址编号,int * pi =&i; //(int *)是pi的类型
14.double arr[5]; //arr是数组名,代表数组的首地址.
double *p; //p是指针变量,指向一个double型的数据
p=arr; //===>p=&arr[0](arr==&arr[0])
arr=p; //ERROR
p={1,2,3}; //ERROR
arr++; //ERROR
p++; //OK
sizeof(arr)=40;sizeof(p)=4;
double* const p2=&d; //p2是个指针常量
arr的真正类型是double[5];
15.const的问题
int i=5;
int *const pi=&i;//指针常量Pi不能修改
pi=&j;//error
*pi=15;//OK
const int *pi2=&i;//常量指针 *pi2不能修改
pi2=&j;//OK
*pi2=15;//error
const int *const pi3=&i;//指向常量的指针常量
pi3=&j;//error
*pi3=15;//error
16.指针作为参数或返回类型
void fn(int arr[5]){
printf("%d\n",sizeof(arr)); //4
}
void fn(int arr[]){
printf("%d\n",sizeof(arr)); //4
}
void fn(int* arr){
printf("%d\n",sizeof(arr)); //4
}
函数定义的格式:返回类型 函数名(参数列表){函数体}
char *fn(char*arr){
returne "wepull”;//数据段常量区
||
char *p="wepull";
return p;
strcpy(arr,"wepull");
return arr;
char *p;
p=malloc(32);
strcpy(p,"wepull");
return p;
static char p[]="wepull";//凡是用“”引起来的内容都存在数据段中,p在栈中,p是数组名,数组占用7个字节的空间
return p;//不要返回局部变量的地址
}
17.指向指针的指针
int i = 3;
int *pi = &i;
int **ppi = π
//给形参指针直接赋值,实参的值并不受影响
18.函数指针
int i;//普通变量
int *pi=&i;//指针变量
void fn(int n){}
void (*fp) (int n) =NULL; //函数指针变量
fp=&fn;
typedef void (*fpType)(int n); //函数指针类型,fpType就是类型名
fpType fp2 = NULL;
19.将一个数组名与一个整数相加就变成一个指针变量了
例如: int a[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
int *p = a[0];//元素的是int
int (*p2)[3] = a;//元素是行:int[3]
int (*p3)[2][3] = &a;//元素是二维数组:int[2][3]
a[0]表示数组第一行第一个元素的地址;a表示数组第0行的地址;&a表示整个数组的首地址
20.double ***a[2][3] a是一个由指向6个double型的指针的指针组成的数组。
21.指针变量本身是占用空间的,本身是有类型的,其次指针变量所指向的空间是有类型的,是有空间的.
22.int func(void)[5]; //error
int func[5](void); //error,
23.&a[0][0]=>a[0] //取地址就是降维
&a[0]===>a
&a=====>&a