今晚复习C语言的指针和数组。
指针
指针:指向一个变量的地址。
声明方式:
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)); }
|
指针的算数运算
指针可以进行++、--、+、-
等运算。
例:指针递增
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 2 3 4 5 6 7 8 9 10 11 12
| #include <stdio.h> int main (){ const char *names[4] = { "Tom", "Bob", "Tony", "Jack" }; int i = 0; while ( i < 4 ) { printf("Value of names[%d] = %s\n", i, names[i] ); i++; } return 0; }
|
指向指针的指针
指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。通常,一个指针包含一个变量的地址。当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。
例:
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;
pptr = &ptr; 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; }
|
指针作为函数参数
当指针(地址)作为函数参数时,函数可以在执行过程中改变指针所指向值:
例:
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); return 0; }
int * getList(){ static int list[5]={1,2,3,4,5}; printf("[getList] &list(%x) => list(%x)\n", &list,list); return list; }
|
数组
一维数组
1 2
| int arr[] = {1,2,3,4,5}; char list[] = {"Tom", "Tony"};
|
多维数组
多维数组可以通过在括号内为每行指定值来进行初始化:
1 2 3 4 5 6 7 8 9 10
| int a[3][4] = { {0, 1, 2, 3} , {4, 5, 6, 7} , {8, 9, 10, 11} };
int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
|
多维数组的访问:
数组作为函数参数
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 28 29 30 31 32
| #include <stdio.h>
double getAverage(int arr[], int size); int main (){ int balance[5] = {1000, 2, 3, 17, 50}; double avg; avg = getAverage( balance, 5 ) ; printf( "平均值是: %f ", avg ); return 0; } double getAverage(int arr[], int size){ int i; double avg; double sum=0; for (i = 0; i < size; ++i) { sum += arr[i]; } avg = sum / size; return avg; }
|
数组作为函数返回值
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 28 29 30 31 32
| #include <stdio.h> #include <stdlib.h> #include <time.h>
int * getRandom(){ static int r[10]; int i; srand( (unsigned)time( NULL ) ); for ( i = 0; i < 10; ++i){ r[i] = rand(); printf( "r[%d] = %d\n", i, r[i]); } return r; }
int main (){ int *p; int i; p = getRandom(); for ( i = 0; i < 10; i++ ) { printf( "*(p + %d) : %d\n", i, *(p + i)); } return 0; }
|
指针和数组的关系
在C语言中,数组名是一个指向数组中第一个元素的常量指针,例如
这个数组中,balance是一个指向&balance[0] 的指针,即数组 balance 的第一个元素的地址。
因此,把 p 赋值为 balance 的第一个元素的地址:
1 2 3 4
| double *p; double balance[10];
p = balance;
|
使用数组名作为常量指针是合法的,反之亦然。因此,*(balance + 4) 是一种访问 balance[4] 数据的合法方式。
把第一个元素的地址存储在 p 中,就可以使用 *p、*(p+1)、*(p+2)
等来访问数组元素(也等同于*list+1
)。