C_Learning(2)
/指针
/指针变量指向一个变量的地址
/给指针变量赋的值只能是地址
/指针变量的赋值
/{ int a; int *p; p=&a; } or { int a; int *p=&a; }
/指针必须先定义后使用
/不能把一个具体的数赋给指针
/ &是取地址运算符,&q 表示取变量 q 的地址
/ *是指针运算符,*p 表示返回指定地址内变量的值
/ 因此,p=&q 表示的是地址;scanf 中 &q 表示往该地址写入操作数;printf 中的 q 表示输出变量 q 地址中存放的操作数;*p 表示输出变量 p 指向的地址中存放的操作数
/ &* 和 *& 的区别
/ & * 的运算优先级相同,按自右向左方向结合
/ &* 表示先进行指针运算,再取地址;(&*p=&(*p)=&a)——是一个地址
/ *& 表示先取地址,再进行指针运算;(*&p=*(&p))——是地址中的操作数
/ 指针的自增自减(p++,p--)造成内存地址按照其所指向的数据类型的直接长度的增或减
/ 指针与数组
/ { int a[100],*p; p=a;}
/ p=a表示将数组 a[100] 的首地址赋给指针变量 p,即 p=&a[0]
/ *(p+n)=*(a+n) ,表示数组 a[100] 第n个元素
/ &a[i][j]、(a[i]+j) 表示第 i 行第 j 列的元素"地址"!
/ 指针与字符串
/ { char *str="hello"; printf ("%s",str); }
/ 这里不是将 hello 赋给指针变量 str ,而是把字符串 "hello" 的首字母地址赋给 str
/ 指针数组
/ { char *str[]={"abc","def","ghi"} }
/ 一个数组,其元素均为指针类型数据,则称为指针数组
/ 由于字符型数组的长度必须大于最长元素的长度,因此,使用指针数组可以大大减少这样的存浪费
/ 指向指针的指针
/ 这种问题只有在实战当中才能得到深刻理解,实例参见:count_even.c / count_even_2.c / count_even_3.c
1 // 统计数组中偶数的个数 2 3 #include <stdio.h> 4 5 int main() 6 { 7 int a[10], *p, **q, i, n=0; 8 printf ("Please input:"); 9 for (i=0; i<10; i++) 10 scanf ("%d",&a[i]); 11 p=a; 12 q=&p; 13 printf ("The array is :"); 14 for (i=0; i<10; i++) 15 { 16 if (*(*q+i)%2==0) 17 { 18 n++; 19 printf ("%5d",*(*q+i)); 20 } 21 } 22 printf ("\n"); 23 printf ("The number is :%d.\n",n); 24 25 return 0; 26 }
1 // 统计数组元素中偶数的个数(2) 2 3 #include <stdio.h> 4 5 int main() 6 { 7 int a[10], *p, **q, n=0; 8 printf ("Please input:\n"); 9 for (p=a; p-a<10; p++) 10 { 11 q=&p; 12 scanf ("%d",*q); 13 } 14 printf ("The array is:"); 15 for (p=a; p-a<10; p++) 16 { 17 q=&p; 18 if (**q%2==0) 19 { 20 printf ("%5d",**q); 21 n++; 22 } 23 } 24 printf ("\n"); 25 printf ("The number is:%d.\n",n); 26 27 return 0; 28 }
1 // 统计数组元素中的偶数个数(3) 2 3 #include <stdio.h> 4 5 int main() 6 { 7 int a[10], *p, n=0; 8 printf ("Please input:\n"); 9 for (p=a; p-a<10; p++) 10 { 11 scanf ("%d",p); 12 } 13 printf ("The array is:\n"); 14 for (p=a; p-a<10; p++) 15 { 16 if (*p%2==0) 17 { 18 printf ("%5d",*p); 19 n++; 20 } 21 } 22 printf ("\n"); 23 printf ("The number is:%d.",n); 24 25 return 0; 26 }
/ 指针变量作函数参数
/ 实例参见swap.c / swap2.c
1 // 交换两个数swap.c 2 3 #include <stdio.h> 4 5 // 定义交换函数swap 6 int swap(int *a, int *b); 7 8 // 主函数 9 int main() 10 { 11 int x, y, *p_x, *p_y; 12 printf ("Please input two number:\n"); 13 scanf ("%d,%d", &x, &y); 14 p_x=&x; 15 p_y=&y; 16 swap(p_x, p_y); 17 printf ("x=%d or *p_x=%d", x, *p_x); 18 printf ("y=%d or *p_y=%d", y, *p_y); 19 20 return 0; 21 } 22 23 // 交换函数swap定义区域 24 int swap(int *a, int *b) 25 { 26 int tmp; 27 tmp=*a; 28 *a=*b; 29 *b=tmp; 30 31 return 0; 32 } 33 34 35 // 为什么不能使用如下源程序swap2.c? 36 /* 37 #include <stdio.h> 38 39 int swap(int a, int b); 40 41 int main() 42 { 43 int x, y; 44 printf ("please input two number:\n"); 45 scanf ("%d%d", &x, &y); 46 swap(x,y); 47 printf ("x=%d.\n", x); 48 printf ("y=%d.\n", y); 49 50 return 0; 51 } 52 53 int swap(int a. int b) 54 { 55 int tmp; 56 tmp=a; 57 a=b; 58 b=tmp; 59 } 60 */ 61 // 在函数调用过程中,主调用函数与被调用函数之间的数值传递是单向的,即只能把实参的值传递给形参,而不能把形参传递给实参。因此,如果使用swap2.c,形参的值会发生改变,但实参的值却不会发生任何变化。 62 // 而使用指针来传递参数,既可以减少值传递带来的开销,也可以使函数调用不产生值传递,即只要保证指针指向的地址是正确的即可。
1 // 交换两个数swap2.c 2 3 #include <stdio.h> 4 5 int swap(int a, int b); 6 7 int main() 8 { 9 int x, y; 10 printf ("please input two number:\n"); 11 scanf ("%d%d", &x, &y); 12 swap(x,y); 13 printf ("x=%d.\n", x); 14 printf ("y=%d.\n", y); 15 16 return 0; 17 } 18 19 int swap(int a. int b) 20 { 21 int tmp; 22 tmp=a; 23 a=b; 24 b=tmp; 25 }
/ 指向函数的指针
/ 指针可以指向函数,一个函数在编译时被分配给一个入口地址,这个函数的入口地址就称为函数的指针
/ 一个函数可以返回一个整型值、字符值、实型值等,也可以返回指针型的数据,即地址
/ 实例见 perimeter.c
1 // 根据指针函数的概念,使用指针函数计算长方形周长 2 3 #include <stdio.h> 4 5 int *per(int a, int b); 6 int perimeter; 7 8 int main() 9 { 10 int width, lenth; 11 int *result; 12 printf ("please input width and lenth:"); 13 scanf ("%d%d", &width, &lenth); 14 result=per(width, lenth); 15 printf ("\nthe perimeter is :%d", *result); 16 17 return 0; 18 } 19 20 int *per(int a, int b) 21 { 22 int *p; 23 p=&perimeter; 24 perimeter=2*(a+b); 25 return p; 26 }
/ 指针数组作 main 函数的参数
/ main 函数可以是无参函数,也可以是有参函数
/ main 函数的带参形式:main(int argc, char *argv[])
/ argc 记录了命令和参数的个数,指针数组 argv[] 的大小由命令和参数的个数决定
/ 实例见main_pointer.c
1 // main 函数的有参实例 2 3 #include <stdio.h> 4 5 main(int argc, char *argv[]) 6 { 7 printf ("the list of parameter:\n"); 8 printf ("command:\n"); 9 printf ("%s\n",*argv); 10 printf ("the number of parameter:"); 11 printf ("%d",argc); 12 } 13 14 // 运行的结果如下: 15 the list of parameter: 16 command: 17 C:\Administrator\Desktop\jan5\main_parameter.exe 18 the number of parameter:1