指针与数组
一、指针与数组
**作用:**利用指针访问数组中元素
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修饰指针有三种情况
- const修饰指针 — 常量指针
- const修饰常量 — 指针常量
- 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);
}