注意:指针变量和普通的变量没有任何的区别
一维指针:
指针大小:
这个是不确定的,要根据编译器来决定,是4字节或者8字节
在32位模式中:位4字节(与类型无关,所有指针数据变量的宽度也是四字节,与指向的数据类型是无关的,比如说char* ,int* ,double*)一个字节=8位(8bit)
指针访问:
char buf[]={1,2,3,4,5,6,7,8,9};
char *addr1=&buf[3];
printf("%d",*addr1);//or printf("%d",addr1[0]);
//这两个输出是一样的 不要把这个看成数组,而是把addr1当作一个门牌号去偏移
//数组也是,数组仅仅是申请空间的一个手段
操作符:
&(取地址操作符):
用法1:
用法2:
用法3:
* (取值操作符)(解引用)
直接传数据不改变原变量,传地址可以改变原变量
1.直接传数据
2.传地址
指针与数组:
数组在内存中的排列时线性的,也就是地址连一块;
所以可以通过指针指向数组的首地址进行操作;
这里面每a每次都增加了4,这个就是一个int的宽度,char就是1,double就是8,所以这里加减的大小就是其去掉一个*以后的数据宽度
当使用函数时想要传数组,其实就是传递数组的首地址
也就是指针变量可以当作数组使用
这里就是在指针上+,加的是按照类型来加的
#include<stdio.h>
int main()
{
//char* s="Aello";//这里面s是个指针,他在栈上,但是他没有空间,他只是指到了只读数据段上
//字符串、常量、都在只读数据段
char s[]="Aello";//这个是定义了一个空间,并不是定义了一把钥匙,定义的是在栈里的一个局部变量,虽然后面的字符串仍然在只读区里,但是行代码实际上做了两件事。1.分配空间2.将"Aello"这个空间拷贝到分配的那个空间里
s[0]='H';//这个s[0]实际上访问的是栈段,栈段是可读可写的
printf("%s",s);//注释掉的那个是无法打印出来的,因为那个定义在只读段里面,无法修改
//%s看的结果也是栈上的结果
return 0;
}
指针强转:
#include<stdio.h>
int main()
{
int a=1025;
// 1025 = 00000000 00000000 00000100 00000001
int *p;
p=&a;
printf("size of integer is %d bytes\n",sizeof(int));
printf("Address = %d ,value = %d\n ",p,*p);// **** 1025
printf("Address = %d ,value = %d\n ",p+1,*(p+1);// ****+4 *****
char* p0;
p0=(char*)p;
//在强转之前,p是4个字节,机器会看4个字节,但是在强转之后,字符型只有一个字节,所以机器只看一个字节,也就是最后的 00000001
printf("size of char is %d bytes \n",sizeof(char));
printf("Address = %d ,value = %d\n ",p0,*p0);// **** 1
printf("Address = %d ,value = %d\n ",p0+1,*(p0+1);// ****+1 4->00000100
return 0;
}
数组作为函数参数:
#include<stdio.h>
int SumOfElements(int A[])//int* A//这里没办法把数组的大小也传过去,只能传一个首地址
{
int i,sum=0;
int size = sizeof(A)/sizeof(A[o]);//
printf("SOE sizeof A = %d,sizeof A[0]=%d",sizeof(A),sizeof(A[0]));// 4 4
for(i=0;i<size;i++)
{
sum+=A[i];
}
return sum;
}
int main()
{
int A[]={1,2,3,4,5};
int total = SumOfElements(A);
printf("Sum of elements = %d\n"total);// 1
printf("Main sizeof A = %d,sizeof A[o]=%d",sizeof(A),sizeof(A[0]));// 20 4
return 0;
}
very important:
二维数组是一维数组的数组,即解引用一次还是得到地址
因为B是数组名,所B是B[0]的地址,即B=&B[0],因此*B=B[0],而B[0]是一维数组的数组名,所以B[0]是B0的地址
b+1 指向b[1] [0] *b+1 b [0] [1]
//运行结果是两个8
多维指针与数组:
如何在函数中传值:
void funa(int *a)// or void funa(int a[])
{
```
}
void funb(int (*b)[3])//or void funa(int a[][3]) int** a是不对的
{
```
}
void Func(int c[][2][2])//or void Func(int (*c)[2][2]) int*** a都是不对的
{
```
}
int main()
{
int a[]={1,2};
int b[2][3]={{2,3,4},
{5,6,7}};
int x[2][4];//这样就不能传到funb函数里面
int c[3][2][2]={{{2,5},{7,9}},
{{3,4},{6,1}},
{{8,0},{11,13}}};
funa(a);//a returns int*
funb(b);//b returns int (*p)[3]的一个一维数组,这个一维数组包含三个整型元素
}
二维指针:
一维指针存放变量地址,二维指针存放一维指针地址。
二级指针的简单用法。。。。,说白了,二级指针保存的是一级指针的地址,它的类型是指针变量,而一级指针保存的是指向数据所在的内存单元的地址,虽然都是地址,但是类型是不一样的
变量就是小姐姐的照片,你再怎么修改照片,小姐姐不会变。但照片依然有作用。指针就是小姐姐本人,你把她脸上涂个黑点,她在任何地方露脸,脸上都会有黑点,这就是本源被修改了。例如a=照片;*p=小姐姐;p=&a;&取地址,就是根据照片找到小姐姐,以后就可以根据p找到她了(就像你找到了小姐姐的家,以后随时都能到马上就到她家门口),也就是可以直接在她脸上涂黑点。此后,她在任何作用域,都是有黑点的小姐姐。