W3 D4指针与数组、常量指针、指针常量

一、指针与数组

**作用:**利用指针访问数组中元素

1、指针与一维数组

int arr[3];
int *p = arr
value: arr[i]   *(arr+i)  *(p+i)   p[i]
addr:  &arr[i]   arr+i	  p+i      &p[i]
int main()
{
	int arr[3] = {4,5,6};
    int i;
	int* p = arr;   //相当于int *p  p=arr;
    
    printf("sizeof(arr) = %ld\n",sizeof(arr));
	printf("sizeof(p) = %ld\n\n",sizeof(p)); 
    //p是指针变量,p是用来存放地址的变量 固定大小8字节
	
	printf("arr = %p\n",arr);
	printf("arr+1 = %p\n\n",arr+1);

	printf("p = %p\n",p);
	printf("p+1 = %p\n\n",p+1);
    
/*  for(i = 0 ; i < sizeof(arr)/sizeof(arr[0]); i++)
		printf("%p --> %d\n",&arr[i],arr[i]);
		printf("%p --> %d\n",p+i,*(p+i));    
*/  	
    
	for(i = 0 ; i < sizeof(arr)/sizeof(arr[0]); i++,p++)
		scanf("%d",p);	
	p = arr;       //p用p++的时候之后必须让p指回来 p = arr
                   //如果不指回来,输入正常输出,但是输出会越界
	for(i = 0 ; i < sizeof(arr)/sizeof(arr[0]); i++)
		printf("%p --> %d\n",&p[i],p[i]);
	printf("\n");

	exit(0);
}

p+i :每次循环p都还是指向初始位置(指向P的位置不会改变)

p++ :每次循环后都会指向下一个位置

注意:

arr常量 arr不能arry++

p指的是存放指针的变量,其余用法均相同,;

int main()
{
	int arr[3] = {4,5,6};
	int i;
	int *p = arr,*q = &arr[2];

	printf("%ld\n",p-q);  //-2
	printf("%ld\n",q-p);  //2   
}

p-q:指的是两个指针相减,得到的是两个指针相差对象的个数

int main_()
{
	int arr[3] = {4,5,6};
	int i = 100,j = 200;
	int *p = arr,*q = &arr[2];
	int *m = &i, *n = &j;     //m就是一个指针 指向i的地址
	int **x = &m, **y = &n;
    
->	*x     **y    **x     *y+1
	int*   int     int    int*    
     &m    200     100     
    
    下述代码发生了什么
0:	*x = n;   //*x = &j *x指向地址i n是指向j地址的指针 把j地址的指针赋值给i 
	*n = 1;   //j=1  n指针存放的是j的地址 *n就是j的值
	**y = 3;  //y指针存放的是n的地址,n指针存的是j的地址 **y就是去j地址里把元素取出来
	**x = 5;  
    
1:	m = n;   //
	*m = 1;  //j=1

2:  *m = 1;
	m = n;
    
}

在这里插入图片描述

2、指针与二维数组

值和地址表示方式

int a[2][3];
int (*p)[3] = a; 
value:  a[i][j]   *(*(a+i)+j)  *(*(p+i)+j)   p[i][j]
addr:  &a[i][j]   *(a+i)+j		*(p+i)+j	 &p[i][j]

2.0 二维数组作为形参

二维数组的存储方式是和一维数组没什么区别,但是用二维数组做参数,它的形参该怎样写?要注意的是:函数中的形参其实就相当于一个声明,并不产生内存分配,形参的目的就是要让编译器知道函数参数的数据类型。

//正确的:
void Func(int array[3][10]); 
void Func(int array[][10]);可以省略第一维的大小
-------------------------------------------------
void Func(int **array, int RowSize, int LineSize);
//在转变后的函数中,array[i][j]这样的式子是不对的
*((int*)array + LineSize*i + j);
//把二维数组当作一维数组来处理,这是比较容易理解的方式
//错误的
//如果在形参中不说明列数,则系统无法决定应为多少行多少列,不能只指定一维而不指定第二维
void Func(int array[3][]);
void Func(int array[][]. //这样的用法只能在初始化时可以用);
//大家都知道数组的索引必须是个常量表达式
void Func(const int m,const int n,int array[m][n]);
void Func(int m,int n,int array[m][n]);

2.1 数组指针本质:

[存储类型] 数据类型 (*指针名)[长度]

是一个指针(指针指向数组,指向的对象是数组)

int a[2][3];
int (*p)[3] = a;     //数组指针 p是用来保存地址的变量

应用:

int main()
{
	int a[M][N] = {{3,4,5},{6,7,8}}; 
	int i,j;
	int (*p)[3];      //数组指针
//	int *p;
	p = a;

	printf("sizeof(a) = %ld\n",sizeof(a));
	printf("sizeof(p) = %ld\n\n",sizeof(p));

	printf("a = %p\n",a);
	printf("a+1 = %p\n\n",a+1);

	printf("p = %p\n",p);
    printf("p+1 = %p\n\n",p+1);
}

在这里插入图片描述

2.2 指针数组本质:

[存储类型] 数据类型 *指针名[长度]

就是一个数组,里面存放的是指针

int a[M][N] = {{3,4,5},{6,7,8}}; 
int i,j,k;
int * p [3] = {&i , &j, &k};
->	p[0]	 p+1	   p++		  p  	 *p
    int *    int*      FFFF      int*    *(p+0)=>p[0]int*
//                    p是数组名           数组里面的值是地址
int main()
{
	int a[M][N] = {{3,4,5},{6,7,8}}; 
	int i = 1,j = 2,k = 3;
	int (*p)[3] = a;   //除了a是常量 b是变量外 p等同于a 
	int *q = *a;
	int *x[3] = {&i,&j,&k};  
    
->	a[0] 	a[1]+1    a[0][0]	  *a		**a		   p[0] 	p+1				
	int*	 int*       int		  int* 	    int		   int*	    int(*)[3]	
   *(a+0)   *(a+1)+1 *(*(a+0)+0)  *(a+0)   *(*(a+0)+0)  *(p+0)
 	
    p[1][1]    *p          *q		q[2]	 q+4     x[0]	     *x		
    int	      int*        int		int		 int*	 int*    	 int*	
              *(p+0)      *(q+0)    *(q+2)            *(x+0)      *(x+0)
 }

(1)、整型指针本质:指针指向整型

3、指针与字符数组

定义方式:

int main()
{
	int i;
	char str[2][32] = {"hello","welcome"};
	char (*p)[32] = str;
	
	for(i = 0 ; i < 2; i++)
		puts(p[i]);        //也可以写成str[i] p与str基本上等价
    
/*	char str[] = "hello";
	char *p = str;

	puts(p);     //hello
	puts(str);   //hello
	puts(p+3);    //lo
	puts(str+3);  //lo
*/    
}

字符指针存储的串常量存储在正文段,不可读,不可写。

int main()
{
	char *p = "world";
	char str[] = "hello";
//T	strcpy(str,p);
//F	strcpy(p,str);

	puts(p);
	puts(str);

/*
	printf("sizeof(p) = %ld\n",sizeof(p));        //8
	printf("sizeof(str) = %ld\n\n",sizeof(str));  //6

	printf("strlen(p) = %ld\n",strlen(p));         //5
	printf("strlen(str) = %ld\n\n",strlen(str));   //5

	puts(p);
	puts(str);
*/
	exit(0);
}

二、指针常量与常量指针(const)

const 常量化 保护

const修饰指针有三种情况

  1. const修饰指针 — 常量指针
  2. const修饰常量 — 指针常量
  3. const即修饰指针,又修饰常量

技巧:看const右侧紧跟着的是指针还是常量, 是指针就是常量指针,是常量就是指针常量

2.1 常量指针

可以改变指针的指向,所指向目标对象的值不可以改变

定义方式:

const int *p;
int const *p;

应用:

int main()
{
	int i = 1,j = 10;
	const int *p = &i;

//F	*p = 100;     //所指向目标对象的值不可以改变
	 p = &j;      //p=10

	printf("%d\n",*p);
}

2.2 指针常量

只是限制了指针的指向,值可以被改变

定义方式:

int * const p;

应用:

int main()
{
	int i = 1,j = 10;
    int * const p = &i;

//T	*p = 100;
	p = &j;     //p=10  

	printf("%d\n",*p);
}

2.3 常量指针常量

保护这一块空间不会被修改

const也叫常量化

定义方式;

const int * const p = &i;
int main()
{
	int i = 1,j = 10;
    const int * const p = &i;

//F    *p = 100;
//F    p = &j;

    printf("%d\n",*p);
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值