C 指针
理解指针定义 --存放地址
内存区的每一个字节有一个编号, 这就是“地址”。 如果在程序中定义了一个变量, 在对程序进行编译
时, 系统就会给这个变量分配内存单元。
在c程序里面有两种访问方式: 1. 是直接访问, 2是间接访问(a的箱子要是在b抽屉里)。
直接访问: a=5;, 系统在编译是,已经对变量分配了地址 如果变量的a的地址是2000, 那么这个语句的作用就是 把常数5保存到地址为2000的单元。
间接访问如:scanf(“%d”, &a);
调用函数时, 把变量a的地址传递给函数scanf, 函数首先把该地址保存到一个单元中, 然后把键盘接受的数据通过所存储的地址保存到a的变量中。
定义指针
int i=5;
int * i_abc; 定义指针变量 i_abc = & i; 存放整型变量i的地址
深入理解:
将i 的内存地址2000存放到i_abc,这时, i_abc的值就是(2000, i的内存地址),即变量i所占用单元
的起始地址。要存取变量i的值,可以采取间接方式:先找到存放“i的地址”的变量i_abc, 然后从中取出i的地址(2000)
然后取出i的值3.
代码讲解
* : 叫取值操作符
&: 叫取址操作符
int i = 5; int *abc; // 这个*不是取值操作符,而是声明他是指针变量, 也就是定义指针变量 abc = &i; // 存放指针,也就是内存地址 &i 的地址是2000 printf("%d\n", *abc);//这个才是取值操作符, 加上*系统知道他是指针的值
注意:
定义的时候:
float a; int *abc; abc = &a; 这样是错误的,关系到取址, 比如有浮点是8位,而整型是4位,那就会少4位
说明:
如果已执行了语句 abc = &a;
1) . &*abc的含义是什么?
"&"和 "*" 两个运算符的优先级相同, 但按照自右而左方向结合, 因此先进行*abc 的运算, 他就是变量a,
例如: printf("%d\n", *abc);
再执行&运算。
2)。 * & a的含义是蛇年意思?
先&a运算,然后在×运算, 最后还是指向a
针对数组的指针 ---------------------------
p= &a【0】 // 把a【0】元素的地址赋给指针变量p
注意一个小地方:
引用一个数组元素, 可以用:
1).下标法, 如a[i]形式; 2).指针法, 如*(a+i) 或(p+1) 其中的a是数组名, p是指向数组元素的指针变量, 其初值p=a。也就是 a指向的数组第一个值 数组名即“翻译成数组的第一个元素地址”
简单易懂的例子
#include <stdio.h> #define N 10 int main(void) { int a[N] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int *p, sum = 0; //方法1: //用索引的方式, 这里需要注意的是p是指针,a[0]是实际的值,需要用&取址 for (p = &a[0]; p < &a[N]; p++) { sum += *p; } printf("sum value is:%d \n", sum); /* sum value is:55 */ //方法2: //用指针的方式 sum = 0; for (p = a; p < a + N; p++) { sum += *p; } printf("sum value is:%d \n", sum); /*sum value is:55*/ return 0; }
要输出数组中的全部元素的三种方法-------一维数组
方法1:下标法
#include <stdio.h> int main(int argc, char const *argv[]) { /* code */ int a[10]; int i; for(i = 0; i < 10; i++) { scanf("%d", &a[i] ); } for(i=0;i<10;i++) { printf("%d\n", a[i]); } return 0; }
方法2: 通过数组名计算数组元素的地址, 找出元素值
#include <stdio.h> int main(int argc, char const *argv[]) { /* code */ int a[10]; int i; for(i = 0; i < 10; i++) { scanf("%d", &a[i] ); } for(i=0;i<10;i++) { printf("%d\n", *(a+i)); } return 0; }
方法3:用指针变量指向数组元素
#include <stdio.h> int main(int argc, char const *argv[]) { int a[10]; int i; int *p; for (i=0;i<10;i++) { scanf("%d", &a[i]); } for (p = a; p < (a+10); p++) { /* code */ printf("%d", *p); } return 0; }
用数组名作为函数参数--------------------------------------------
f(int a[], int n) 但在编译时是将arr按指针变量处理的, 相当于将函数f的首部写成f(int *arr, int n) 等价的
看试题:
要求将数组a中n个整数按相反顺序存放
#include <stdio.h> int main(int argc, char const *argv[]) { void reverse(int *x, int); int i, a[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2}; for (i = 0; i < 10; i++) { printf("%d", a[i]); } printf("\n"); reverse(a, 10); for (i = 0; i < 10; i++) { printf("%d", a[i]); } printf("\n"); return 0; } void reverse(int x[], int n) { int temp, i, j, m; m = (n-1)/2; for (i = 0; i <= m; i++) { j = n-1-i; temp = x[i]; x[i] = x[j]; x[j] = temp; } }
指针写法
#include <stdio.h> int main(int argc, char const *argv[]) { void reverse(int *x, int); int i, a[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2}; for (i = 0; i < 10; i++) { printf("%d", a[i]); } printf("\n"); reverse(a, 10); for (i = 0; i < 10; i++) { printf("%d", a[i]); } printf("\n"); return 0; } void reverse(int *x, int n) { int *p, temp, *i, *j, m; m = (n - 1)/2; i = x; j = x + n -1; p = x + m; for (;i <= p;i++, j--) { temp = *i; *i = *j; *j = temp; } }
二维数组
内存地址
怎么用指针寻找的规律
从前面的图可以分析得出结论 *(p+i) + j 是二维数组i行j列的元素地址
而*(*(p+i) +j) 则是i行j列的值
定义多维数组元素的指针变量
把二维数组a分解为一维数组a[0], a[1], a[2]之后, 设p为指向二维数组的指针变量
可定义为:
int (*p)[4]
表示p是一个指针变量, 他指向包含4个元素的一维数组。 若指向第一个一维数组a[0], 其值等于a,
a【0】, 或&a【0】【0】等。
#include <stdio.h> int main(int argc, char const *argv[]) { int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11}; int (*p)[4]; int i, j; p = a; for (i=0; i < 3; i++) { /* code */ for (j = 0;j<4;j++) { // printf("%2d", *(*p+i)+j); //注意这个错误,是我当初犯下的错误 printf("%2d", *(*(p+i)+j)); } printf("\n"); } return 0; }
字符串与指针 --------------------------------------
用数组的形式来表示字符串
#include <stdio.h> int main(int argc, char const *argv[]) { char string[] = "I love you , Future girl" ; printf("%s\n", string); return 0; }
用指针的形式
#include <stdio.h> int main(int argc, char const *argv[]) { char *string = "I love you , Future girl" ; printf("%s\n", string); return 0; }
对字符串中的字符的存取方法有两种
1. 是下标法:
#include <stdio.h> int main(int argc, char const *argv[]) { char a[] = "hahhahahaha, future girl", b[40]; int i; for (i = 0; *(a + i) != '\0'; i++) { *(b + i) = a[i]; } *(b + i) = '\0'; printf("%s\n", a); printf("%c\n", *a); for (i = 0; b[i] != '\0'; i++) { printf("%c", b[i]); } printf("\n"); return 0; }
2.是指针方法:
#include <stdio.h> int main(int argc, char const *argv[]) { char a[] = "hahhahahaha, future girl", b[40], *p1, *p2; int i; p1 = a; p2 = b; for (; *p1 != '\0'; p1++, p2++) { *p2 = *p1; } *p2 = '\0'; printf("wo shi a:%s\n", a); for (i = 0; b[i] != '\0'; i++) { printf("%c", b[i]); } return 0; }
字符指针作函数参数以及指针a【】和*a 的区别 -----------------------------
*a 是不可写的,a【】是可写的
为什么: char *a = "i am a;"; 是放常量的,常量是不可写的。
在c/c++中,内存分为5个区, 堆,栈, 自由存储区, 全局/静态存储区和常亮存储区。
方法一:用字符串数组作参数
#include <stdio.h> int main(int argc, char const *argv[]) { int copy_str(char from[], char to[]); char a[] = "i am a;"; char b[] = "i am b;"; printf("%s\n%s\n----------------\n", a, b); copy_str(a, b); printf("%s\n%s\n", a, b); return 0; } int copy_str(char from[], char to[]) { int i = 0; while (from[i] != '\0') { to[i] = from[i]; i++; } to[i] = '\0'; return 0; }
方法二: 形参用字符指针变量
#include <stdio.h> int main(int argc, char const *argv[]) { int copy_str(char *from, char *to); char *a = "i am a;"; char b[] = "i am b;"; //注意这是b是不是为×b,否则报错不能写入 printf("%s\n%s\n----------------\n", a, b); copy_str(a, b); printf("%s\n%s\n", a, b); return 0; } int copy_str(char *from, char *to) { for (; *from != '\0'; from++, to++) { *to = *from ; } return 0; }
还有一种巧妙方法
#include <stdio.h> int main(int argc, char const *argv[]) { int max(int, int); int (*p)(); int a, b, c; p = max; scanf("%d %d", &a, &b ); c = (*p)(a, b); //关键是这句 printf("%d, %d\n", a, b); printf("%d\n", c); return 0; } int max(int x, int y) { int z; if (x > y) { z = x; } else { z = y; } return z; }
小需求及测试题
注意,指针函数 的写法
int *test(int a[]);
返回指针的数组元素的写法
int *test(int a[]){ return &a[3]; }
用&符号
参考代码:
只写了一部分
#include <stdio.h> #define N 5 int *test(int a[]); int main(void) { int b[N] = {1, 2, 3, 4, 5}; int *a=NULL; a = test(b); printf("%d\n", *a); return 0; } int *test(int a[]){ return &a[3]; }
#include <stdio.h> #define N 5 void find_two_largest(int a[], int n, int *largest, int *second_largest); int main(void) { int b[N] = {1, 2, 3, 4, 5,}; int largest = 0, second_largest = 0; find_two_largest(b, N, &largest, &second_largest); printf("largest value is: %d \n", largest); printf("second_largest value is: %d \n", second_largest); return 0; } void find_two_largest(int a[], int n, int *largest, int *second_largest) { *largest = *second_largest = a[0]; for (int i = 0; i < n; ++i) { if (a[i] > *largest) *largest = a[i]; } for (int i = 0; i < n; ++i) { if (a[i] == *largest) { continue; } else if (a[i] > *second_largest) { *second_largest = a[i]; } } }
出处:http://www.cnblogs.com/renfanzi/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。