C语言指针、二维数组和指针

指针------
指针就是变量的地址,存放指针的变量就是指针变量。在指针变量中不是存放具体的数据,而是存放其他变量的地址即存放其他变量的指针。
int * p;//定义指针 *是说明符,说明p是指针。
p = &a;//地址是16进制存储的
printf(“%p\n”,p);//地址
printf(“%lu\n”,sizeof(p));//指针占8个字节
printf(“%d\n”,*p);//* 是运算符,是一次寻址运算
int *p=NULL;//指向空地址

char *pc=NULL;
short *ps=NULL;
int *pi=NULL;
long *pl.=NULL;
float *pf=NULL;
double *pd=NULL;
printf(“sizeof(pc)=%lu\n”,sizeof(pc));
printf(“sizeof(ps)=%lu\n”,sizeof(ps));
printf(“sizeof(pl.)=%lu\n”,sizeof(pl.));
所有指针大小都一样的,都是八个字节。
指针的运算----
指针只有两种运算,加和减
指针的加法向下偏移,根据地址向下偏移,依赖于自己的类型。
多级指针:
int a = 100;
int * p = &a;
int **pp = &p;//**pp二级指针,存储一级指针的地址
printf(“&a=%p\n”,&a);//a的地址
printf(“p=%p\n”,p);//a的地址
printf(“&p=%p\n”,&p);//一级指针变量的地址
printf(“pp=%p\n”,pp);//一级指针p 的地址
printf("*p=%d\n",*p);//a的值
printf("*pp=%p\n",*pp);//a的地址
printf("**pp=%d\n",**pp);//a的值
p = &a
*p = a
pp = &p
*pp = p = &a
**pp = *p = a
函数和指针-------
void swap(int a,int b);//函数的按值传递
void swap(int *a,int *b);//函数按地址传参数
数组传参---------
数组的传参时按地址传递的
二维数组---------
void print_arr2(int arr[][4],int m )
{
}
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
变量的指针和指向变量的指针变量。
1.变量的指针就是变量的地址。存放变量地址的变量是指针变量,它用来指向另一个变量。
为了表示指针变量和它所指向的变量之间的联系,在程序中用“*”符号标识标志“指向”。
如果已定义了i_pointer为指针变量,则(*i_pointer)是i_pointer所指向的变量。
可以看到,*i_pointer也代表一个变量,它和变量i是同一回事。
2.指针变量是专门存放地址的,不同与其他类型变量。
int * i_pointer; i_pointer,它是指向整型变量的指针变量。int 是在定义指针变量时必须指定的“基类型”。指针变量的基类型用来指定该指针变量可以指向的变量类型(指针变量所指向的类型)。*i_pointer表示i_pointer所指向的变量(指针变量所指向的变量)。
指针的理解:
内存中: 值 变量 地址
2 a 0x0001
int a = 2;//定义整型变量a
int * p1 = &a;// 定义一个指针变量p1指向 类型为int的指向a的地址指针变量。
int * p1 = 2;//这是不正确的!p1只能接受地址。
*p1 = 2;//这样是正确的。因为p1已经指向了一个指针,这里可以通过指针变量指向的变量修改value;
printf(“%p,%d”,p1,*p1);//p1为地址,*p1的*为访问地址p1的变量值。p1为地址。
int arr[4]={1,2,3,4};//定义数组arr。arr=&arr[0],arr为数组的首地址。
int * p2 = arr;//指针变量p2指向arr首地址。
printf("%p,%d\n",p2,*p2);//p2为0x7fff5fbff7e0,arr的首地址, *p2为1,*访问p2的值。
//访问数组的其他元素。
printf("%p,%d\n",&p2[1],*&p2[1]);//访问第二个元素的地址方法为&p2[1],不能为p2[1]。p2[1]类似a这种方式的变量名,如果需要访问他的地址需要加&,同理如果要访问其中的元素需要通过 * *p2能访问arr数组首个值,因为是p2已经是arr的首地址了。
char c1=‘A’;
char * p3 = &c1;//char类型的指针变量
printf(“%p,%c,%c\n”,p3,*p3,p3[0]);// 访问方式同 p1, p3[0]也可以访问,p1也行。
char c2[20]=“hello world!”;//字符串c2
char * p4 = c2;//p4访问字符数组,
*p4 = *p3;//value发生变化,地址不变
*&p4[0]=*p4;
&p4[0] =&*p4;
printf("%p,%p,%c,%c\n",p4,&p4[1],*p4,*&p4[1]);//p4指向首地址,p4和&p4[0]相同。访问内容方式相同,因为是字符数组,所有输出的是char类型的。
1.指针p5和p6地址发生变化,值发生变化,aa和bb 不变。
int aa = 5;
int bb = 9;
int *p5,*p6,*temp;
p5 = &aa;
p6 = &bb;
printf("p5=%p,p5=%d,p6=%p,p6=%d,aa=%d,bb=%d\n",p5,*p5,p6,*p6,aa,bb);
if (aa < bb) {
temp = p5;
p5 = p6;
p6 = temp;
}

printf("p5=%p,p5=%d,p6=%p,p6=%d,aa=%d,bb=%d\n",p5,*p5,p6,*p6,aa,bb);
2.通过地址将aa和bb的value发生变化。aa的值和bb的值发生变化。但是地址不发生变化。
只所以用temp做中间变量 是因为,int temp和*p1是等价的。
swap(&aa,&bb);
void swap(int * p1,int * p2)
{
int temp;
temp = *p1;
*p1=*p2;
*p2=temp;

}
3.使用int *temp;做中介变量就有问题了,temp是指针变量,而temp所指向的地址为空,所以*temp没发赋值。
但是如果temp指定了初始地址就可以来,我们随便申请一个a的内存地址。然后给temp指定。这时候在用*temp做中间变量就行来,这时候点*temp和a是等同的。
void swap1(int * p1,int * p2)
{
int a = 0;
int *temp;//如果修改为int *temp = &a;这样就行了。给来初始指定地址,里面的变量就可以使用了。
*temp = *p1;//语法有问题。
*p1=*p2;
*p2=*temp;
}
4.这种写法是无法完成调用函数的值的转换的。
void swap2(int x,int y)
{
int temp;
temp = x;
x = y;
y = temp;
}
5.结果是无法进行调换的(函数无法修改指针变量的值,但是可以修改指针变量所指向的值,p1和p2是当作参数在函数中使用的,地址的调换只在本次函数中生效,其实并没有修改指针变量所指向的值)。C语言中实参变量和行参变量之间的数据传递是单向的“值传递”方式。指针变量作函数参数也要遵循这一规则。不可能通过调用函数来改变实参指针变量的值。但可以改变实参指针变量所指变量的值。
void swap2(int * p1,int * p2)
{
printf("p1=%p,p2=%p\n",p1,p2);
int *temp;
temp = p1;
p1=p2;
p2=temp;
printf("p1=%p,p2=%p\n",p1,p2);
}
------------------
1.多维数组元素的地址--------
a[i]和*(a+i)在一维数组中是取值,取得&a[i]和(a+1)地址中的值。
在二维数组中,a[i]和*(a+i)代表取得的是i行的地址。
所以a+i和*(a+i)是相同的,都是取得i行的地址。
*(a+i)+j取得,i行j列的地址,和&a[i][j]、a[i]+j是相同的。
具体取值,*(*(a+i)+j)、a[i][j]、*(a[i]+j)取得地址所对应的值。

int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
//二维数组名,指向一维数组a[0],即0行首地址。
printf("a=%p\n",a);
//0行0列元素地址
printf("a[0]=%p,*(a+0)=%p,*a=%p\n",a[0],*(a+0),*a);
//1行首地址
printf("a+1=%p,&a[1]=%p\n",a+1,&a[1]);
//1行0列元素地址,a[1][0]地址
printf("a[1]=%p,*(a+1)=%p\n",a[1],*(a+1));
//1行2列元素地址,a[1][2]地址
printf("a[1]+2=%p,*(a+1)+2=%p,&a[1][2]=%p\n",a[1]+2,*(a+1)+2,&a[1][2]);
//1行2列元素值,a[1][2]值
printf("*(a[1]+2)=%d,*(*(a+1)+2)=%d,a[1][2]=%d\n",*(a[1]+2),*(*(a+1)+2),a[1][2]);
2.指向多维数组元素的指针变量--------
字符串输入空格问题 接受字符串使用%[^\n];
char aaa[100];
printf(“aaa=");
scanf("%[^\n]",aaa);
printf("aaa=%s\n",aaa);
一维数组的延伸 -----
数组的定义
int a[5];和int a[5]={0};区别,不赋值的话,内存中使用的是上一次使用内存的数据,可能会存在垃圾数据问题。建议使用={0}赋值初始化。
int a,和int a = 0;的道理是一样的。
定义变量后建议使用初始化(清理垃圾步骤)。
int a[5]={1};//a[0] = 1,a[1]=0,a[2]=0……只有第一个被初始化为1,其他位零。
二维数组----------
int a[3][4];//3行,4列

静态变量:static
//静态内部变量
1、存储区域 全局区(静态存储区)。
2、作用域 函数体内。
✅3、生命周期 整个程序。因为是static静态,所以不释放,换句话说内部静态变量x 只被初始化了一次(内部静态变量只初始化一次)。
✅ 补充说明:无论生成了多少个对象,都只有一个静态变量,也就是说多个对象会共享一个静态变量。函数体外定义的全局变量也是同样的道理。

4、
void A()
{
static int x = 1;
printf(“x=%d\n”,x);
}
A();
A();
A();
打印出来 2,3,4;

函数和函数是独立的。不能函数包含函数。不允许在函数体内定义子函数。
void A();函数声明。
函数先声明后使用。
新建c file时,生成.c和.h两个文件,.c是函数实现部分。.h是函数的声明部分。
如果要在main.c中引用AA.c需要在main.c中#include “AA.h”;引用头文件。
#include<> 查找系统路径。
#include” ” 先查找用户路径,找不到再找系统路径。
extern 跨文件访问全局变量x
extern int x;
如果全局变量定义在AA.c中int sum = 200;
可以在AA.h中定义
extern int sum;
这样在main.c中导入头文件后,可以直接使用sum了。
#define 需要定义在.h里面,然后main可以使用
static int qq = 20;//静态全局变量 在main.h中无法使用。
-----静态全局变量
1、存储区域 全局区
2、作用域 本文件
3、生命周期 整个程序
static静态文件无法跨文件使用。
static void M();//静态函数,只能在本文件中使用。
------
数组:
1.一组相同数据类型的的数据的有序集合,这些数据用一个数组名称来访问。
2.数组均有连续的存储单元组成,最低地址对应于数组的第一个元素,最高地址对应于最后一个元素。
一维数组:
初始化:int a[5]={1,2,3,4,5};
a[0]=100;//数组修改
变量名 变量值 地址
a[0] 100 0x0010

--------------------------------------------------------------------------------
数组与指针
一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。指针变量既然可以指向变量,当然也可以指向数组元素(把某一元素的地址放到一个指针变量中)。所谓数组元素的指针就是数组元素的地址。
int a[10];
int *p;
p=a;//把a数组的首元素的地址赋给指针变量p。不是把数组a各元素的值给p。
p=&a[0];
通过指针引用数组元素。
printf("%p,%p,%d,%d\n",p+1,a+1,*(p+1),*(a+1));//p+i 和a+i 就是a[i] 的地址。
指针p指向的是a的首地址,a也是该数组的首地址。所以p=a
根据p想查找其他元素的话,可以使用p+i,p+i访问的是第i个地址。
(p+i)=(a+i)=&a[i]=&p[i] 地址
*(p+i)=*(a+i)=*&a[i]=*&p[i]=a[i]=p[i] 变量名
for (p = a; p<(a+10);p++) {//使用指针循环,p指针每次想后移动一个元素。
printf("%p,%d\n",p,*p);
}
*p++ 先算*p然后加1
*(p++) 指针指向下一个元素,然后要地址变量名



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值