今晚复习C语言的指针和数组。
指针
指针:指向一个变量的地址。
声明方式:
1 | int *p; |
C语言**ptr**变量名的含义:pts就是**Pointer Recod(er)**的简写
指针的使用:定义指针变量、把变量地址赋值给指针、访问指针变量指向的地址的值。
空指针:指向0x0,啥也不是。
指针的值:指针的值的类型都是一样的,长度等于一个单位地址的长度的16进制数值(32位、64位等)
指针的类型:指针指向的数据类型必须是一个有效的 C 数据类型。
例如,在32位系统中:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <stdio.h>
int main (){
int *p;
char *t;
printf("Length of p: %d\n", sizeof(p));
printf("Length of t: %d\n", sizeof(t));
printf("Length of *p: %d\n", sizeof(*p));
printf("Length of *t: %d\n", sizeof(*t));
}
/*
执行结果:
Length of p: 4
Length of t: 4
Length of *p: 4
Length of *t: 1
*/
指针的算数运算
指针可以进行++、--、+、-
等运算。
例:指针递增1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <stdio.h>
const int MAX = 3;
int main (){
int var[] = {10, 100, 200};
int i, *ptr;
/* 指针中的数组地址 */
ptr = var;
for ( i = 0; i < MAX; i++) {
printf("存储地址:var[%d] = %x\n", i, ptr );
printf("存储值:var[%d] = %d\n", i, *ptr );
/* 移动到下一个位置 */
ptr++;
}
return 0;
}
指针数组
可以通过指针来声明数组
1 | #include <stdio.h> |
指向指针的指针
指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。通常,一个指针包含一个变量的地址。当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。
例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include <stdio.h>
int main (){
int var;
int *ptr;
int **pptr;
var = 3000;
ptr = &var; // 取var的地址作为指针ptr的值
pptr = &ptr; // 取ptr的地址作为pptr的值
printf("&var(%x) => var(%d)\n", &var, var );
printf("&ptr(%x) => ptr(%x) => *ptr(%d)\n", &ptr, ptr,*ptr );
printf("&pptr(%x) => pptr(%x) => **pptr(%d)\n", &pptr, pptr, **pptr);
return 0;
}
/*
执行结果:
&var(ffe3b11c) => var(3000)
&ptr(ffe3b118) => ptr(ffe3b11c) => *ptr(3000)
&pptr(ffe3b114) => pptr(ffe3b118) => **pptr(3000)
*/
指针作为函数参数
当指针(地址)作为函数参数时,函数可以在执行过程中改变指针所指向值:
例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <stdio.h>
#include <time.h>
void getSeconds(unsigned long *par);
int main (){
unsigned long sec;
printf("[main] &sec(%x)=>sec(%ld): \n", &sec,sec);
getSeconds( &sec );
printf("[main] sec: %ld\n", sec );
return 0;
}
void getSeconds(unsigned long *par){
printf("[getSeconds] &par(%x)=>par(%x): \n", &par, par);
/* 获取当前的秒数 */
*par = time( NULL );
return;
}
指针作为函数返回值
指针作为函数返回值时,调用方可以直接访问这个地址:
例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <stdio.h>
int * getList();
int main (){
int * i;
int j;
printf("[main] &i(%x) => i(%x)\n", &i,i);
i = getList();
printf("[main] &i(%x) => i(%x)\n", &i,i);
//for(j=0;j<5;j++)
// printf("%d\t", i[j]);
return 0;
}
int * getList(){
static int list[5]={1,2,3,4,5};
printf("[getList] &list(%x) => list(%x)\n", &list,list);
return list;
}
/*
执行结果:
[main] &i(ff94f03c) => i(5661b25b)
[getList] &list(5661e01c) => list(5661e01c)
[main] &i(ff94f03c) => i(5661e01c)
*/
数组
一维数组1
2int arr[] = {1,2,3,4,5};
char list[] = {"Tom", "Tony"};
多维数组
多维数组可以通过在括号内为每行指定值来进行初始化:
1 | int a[3][4] = { |
多维数组的访问:1
int val = a[2][3]; //获取数组中第2行第3个元素
数组作为函数参数
1 | #include <stdio.h> |
数组作为函数返回值
1 | #include <stdio.h> |
指针和数组的关系
在C语言中,数组名是一个指向数组中第一个元素的常量指针,例如
1 | double balance[50]; |
这个数组中,balance是一个指向&balance[0] 的指针,即数组 balance 的第一个元素的地址。
因此,把 p 赋值为 balance 的第一个元素的地址:1
2
3
4double *p;
double balance[10];
p = balance;
使用数组名作为常量指针是合法的,反之亦然。因此,*(balance + 4) 是一种访问 balance[4] 数据的合法方式。
把第一个元素的地址存储在 p 中,就可以使用 *p、*(p+1)、*(p+2)
等来访问数组元素(也等同于*list+1
)。