C语言指针详解
2010-12-02 09:18
288 查看
/**
* 指针简介
* 可以有效地表示复杂的数据结构
* 能动态分配内存
* 方便地使用字符串
* 有效而方便地使用数组
* 在调用函数时能获得一个以上的结果
* 能直接处理内存单元地址
*/
//地址与指针的概念?
/**
为了说清楚什么是指针,必须弄清楚数据在内存中是如何存储的,又是如何读取的。
声明一个变量,在编译时,系统会给变量分配内存单元(内存空间),内存区的每一个字节有一个编号,这就是"地址",
地址所标志的内存单元中存放数据。
变量的存储与读取流程
定义整型变量i,编译时系统分配2000、2001两个字节给变量i。
在程序中一般是通过变量名来对内存单元进行存取操作的。
程序经过编译后已经将变量名转化成变量的地址,对变量值的存取都是通过地址进行的。
printf("%d", i)
根据变量名与地址的对应关系,找到变量i的地址2000,然后从2000开始的两个字节中取出数据,把它输出。
scanf("%d", &i)
把从键盘输入的值送到地址为2000开始的整型存储单元中。
这种通过变量地址直接存取变量的方式称为"直接访问"方式。
另外一种方式是间接访问,即将变量i的地址存放在另一个变量中,这种变量称为指向变量的指针变量。
int * i_pointer; //i_pointer是指向int型变量的指针变量
i_pointer = &i; //将i的地址2000存放到i_pointer中。
一个变量的地址称为该变量的指针,例如地址2000是变量i的指针。
存放变量地址的变量为指针变量,i_pointer为指针变量。
*指针运算符(或称"间接访问运算符"),取其指向的内容。
i_pointer为指针变量,* i_pointer为i_pointer指向的内容。
i = 3; 等价于 * i_pointer = 3
*/
/**
1. & * i_pointer的含义?
& * i_pointer 相当于 &i
2. * &i的含义?
* &i 相当于 i
3. (* i_pointer)++ 相当于 a++
*/
* 指针简介
* 可以有效地表示复杂的数据结构
* 能动态分配内存
* 方便地使用字符串
* 有效而方便地使用数组
* 在调用函数时能获得一个以上的结果
* 能直接处理内存单元地址
*/
//地址与指针的概念?
/**
为了说清楚什么是指针,必须弄清楚数据在内存中是如何存储的,又是如何读取的。
声明一个变量,在编译时,系统会给变量分配内存单元(内存空间),内存区的每一个字节有一个编号,这就是"地址",
地址所标志的内存单元中存放数据。
变量的存储与读取流程
定义整型变量i,编译时系统分配2000、2001两个字节给变量i。
在程序中一般是通过变量名来对内存单元进行存取操作的。
程序经过编译后已经将变量名转化成变量的地址,对变量值的存取都是通过地址进行的。
printf("%d", i)
根据变量名与地址的对应关系,找到变量i的地址2000,然后从2000开始的两个字节中取出数据,把它输出。
scanf("%d", &i)
把从键盘输入的值送到地址为2000开始的整型存储单元中。
这种通过变量地址直接存取变量的方式称为"直接访问"方式。
另外一种方式是间接访问,即将变量i的地址存放在另一个变量中,这种变量称为指向变量的指针变量。
int * i_pointer; //i_pointer是指向int型变量的指针变量
i_pointer = &i; //将i的地址2000存放到i_pointer中。
一个变量的地址称为该变量的指针,例如地址2000是变量i的指针。
存放变量地址的变量为指针变量,i_pointer为指针变量。
*指针运算符(或称"间接访问运算符"),取其指向的内容。
i_pointer为指针变量,* i_pointer为i_pointer指向的内容。
i = 3; 等价于 * i_pointer = 3
*/
/**
1. & * i_pointer的含义?
& * i_pointer 相当于 &i
2. * &i的含义?
* &i 相当于 i
3. (* i_pointer)++ 相当于 a++
*/
#include <stdio.h> void pointer_int(); void pointer_compare(); void pointer_swap(); void index_method(); void pointer_method(); void array_reverse(); void multi_arr(); void str_poiner(); void main() { pointer_int(); pointer_compare(); pointer_swap(); index_method(); pointer_method(); array_reverse(); multi_arr(); str_poiner(); } //通过指针变量访问整型变量 void pointer_int() { int a=100, b=10; int * pointer1, * pointer2; pointer1 = &a; pointer2 = &b; printf("%d, %d/n", a, b); printf("%d, %d/n", * pointer1, * pointer2); } //输入a,b两个整数,按先大后小的顺序输出a和b void pointer_compare() { int *p, *p1, *p2, a, b; scanf("%d, %d", &a, &b); p1 = &a; p2 = &b; if (a < b) { p = p1; p1 = p2; p2 = p; } printf("a=%d, b=%d/n", a, b); printf("max=%d, min=%d/n", *p1, *p2); } //指针变量作为函数参数 /** 函数的参数不仅可以是整型,浮点型,字符型等数据,还可以是指针类型。 它的作用是将一个变量的地址传送到令一个函数中。 */ void pointer_swap() { void swap(int *p1, int *p2); int a, b; int *pointer_1, *pointer_2; scanf("%d, %d", &a, &b); pointer_1 = &a; pointer_2 = &b; if (a < b) { swap(pointer_1, pointer_2); } printf("a=%d, b=%d/n", a, b); } //如果a<b, 则a与b的值就改变了 void swap(int *p1, int *p2) { int temp; temp = *p1; *p1 = *p2; *p2 = temp; } /** * 数组与指针 * * 指针变量既可以指向变量,也可以指向数组元素(把某一元素的地址放到一个指针变量中)。 * 所谓数组元素的指针就是数组元素的地址 * * int a[10]; 定义a为包含10个整型元素 * int *p; 定义p为指向整型变量的指针变量 * p = &a[0]; p = a; 把数组的第一个元素的地址赋给p * * int *p; p=&a[0]; 等价于 int *p = &a[0]; 把&a[0]赋给了p而不是*p */ /** * 按C语言规定,如果指针变量p已指向数组中的一个元素,则p+1指向同一数组中的下一个元素。 * 指向数组的指针变量也可以带下标,如p[i]与*(p+i)等价。 * 引用数组元素的方法: * 1.下标法,如a[i]形式 * 2.指针法,如*(p+i) */ //假设有一个a数组,整型,有10个元素,输出各元素的值。 void index_method() { //下标法 int a[10] = {0,1,2,3,4,5,6,7,8,9}; int i; for(i=0; i<10; i++) { printf("%d", a[i]); } printf("/n"); } void pointer_method() { //指针法 int a[10] = {0,1,2,3,4,5,6,7,8,9}; int *p; //&a[0]+10是第十个元素下一个元素的首地址 //(p=&a[0]; p<(&a[0]+10); p++) 也可以写成 (p=a; p<(a+10); p++) for(p=&a[0]; p<(&a[0]+10); p++) { printf("%d", *p); } printf("/n"); } /** * 用数组名作函数参数 * 用数组名作为函数参数的情况,实参数组名代表该数组首元素的地址,而形参是用来接收从实参传递过来的数组首元素地址的。 * 因此,形参应该是一个指针变量(只有指针变量才能存放地址)。实际上,C编译器都是将形参数组名作为指针变量来处理的。 * f(int arr[], int n) 等价于 f(int *arr, int n) * 以上这两种写法是等价的。在该函数被调用时,系统会建立一个指针变量arr。 * 用来存放从主调函数传递过来的实参数组首元素的地址。 * 当 arr接收了实参数组的首元素地址后,arr就指向实参数组首元素,也就是指向了array[0],arr+1 指向 array[1]... */ //将数组a中n个整数按相反顺序存放 void array_reverse() { void inv(int *x, int n); int i,a[10]={3,7,9,11,0,6,7,5,4,2}; printf("The array:/n"); for(i=0;i<10;i++) { printf("%d", a[i]); } printf("/n"); inv(a, 10); printf("The array has been inverted:/n"); for(i=0;i<10;i++) { printf("%d", a[i]); } printf("/n"); } void inv(int *x, int n) { int *p,temp,*i,*j,m=(n-1)/2; i=x; j=x+n-1; p=x+m; for(;i<=p;i++,j--) { temp=*i; *i=*j; *j=temp; } } /** * 多维数组和指针 * 用指针变量输出二维数组元素的值 */ void multi_arr() { int a[3][4] = {{1,3,5,7},{9,11,13,15},{17,19,21,23}}; int *p; for(p=a[0];p<a[0]+12;p++) { if ((p-a[0])%4 == 0) printf("/n"); printf("%-4d", *p); } printf("/n"); } /** * 字符串与指针 * 在C中,有两种方法访问一个字符串 * 1.字符数组 char string[] = "Hello Word!"; * 2.字符指针 char *string = "Hello Word!"; 把字符数组第一个元素的的地址赋给string */ //用字符指针实现字符串的复制 void str_poiner() { void copy_string(char *from, char *to); char *a = "I am a teacher."; char *b = "You are a student."; printf("string a=%s/nstring b=%s/n",a,b); printf("/ncopy string a to string b:/n"); copy_string(a,b); printf("/nstring a=%s/nstring b=%s/n",a,b); } void copy_string(char *from, char *to) { for(;* from!='/0';from++, to++) { *to = *from; } * to='/0'; } /** * 指向函数的指针 * 指针可以指向变量,字符串,数组等,也可以指向一个函数。一个函数在编译时被分配给一个入口地址。 * 这个函数的入口地址就称为函数的指针。 * 指向函数的指针变量的一般定义形式 * 数据类型 (* 指针变量名)(函数参数列表); */ void poniter_function() { int max(int, int); int (*p)(int, int); int a,b,c; p=max; scanf("%d,%d",&a,&b); c=(*p)(a,b); printf("a=%d,b=%d,max=%d/n",a,b,c); } /** * 返回指针值的函数 * 一个函数可以返回整型值、字符值、实型值,也可以返回指针型的数据,即地址。 * 类型名 * 函数名(参数列表) */ /** * 指针数组和指向指针的指针 * 指针数组 * 一个数组,若其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都相当于一个指针变量。 * 为什么会用到指针数组呢,这是因为它比较适合于用来指向若干个字符串。 * char * str[]; * str[0] -> "Hello" * str[1] -> "Word" * * 指向指针的指针 * 指向指针数据的指针变量,简称为指向指针的指针 * char **p; 指针变量p指向一个字符指针变量。 */ //使用指向指针的指针 void p_ponier() { char * name[] = {"Hello Word", "welcome", "Great Wall"}; char **p; int i; for(i=0;i<3;i++) { p=name+i; printf("%s/n", *p); } } /** * 指针数组作为main函数的参数 * argc和argv都是main函数的形参。main函数是由操作系统调用的。 * 命令行状态下argc为参数个数,argv是指针数组,是向程序传入的参数。 * 命令名 参数1 参数2 ... 参数n */ //void main(int argc, char * argv[]) //void main(int argc, char ** argv) /** * ** argv为一个指向指针的指针,argv指向的是 * argv[]指针数组中的元素。 */