- 指针类型相关的基础知识
- 指针与指针变量的概念,指针与地址运算符
- 指针
- 指针变量
- 例子
- 指针变量的基类型的作用
- 定义指针变量
- 给指针变量赋值
- 使指针指向一个对象
- 指针与地址运算符
- &是取地址运算 对任意变量都可以进行取地址操作
- *是取指针目标运算符
- 指针和指针变量的区别:
- 指针和指针变量的关系
- 通过指针引用数组
- 通过指针引用数组元素
- 几个注意的问题:
- 数组名作函数参数
- 指向多维数组的指针和指针变量
- 通过指针引用字符串
- C语言表示字符串的两种表示法
- 几种将字符型指针变量指向字符串的正确方法:
- 字符指针作为函数参数
- 1. 用字符数组名作参数
- 2. 字符型指针变量作实参
- 3. 用字符指针变量作形参和实参
- 指针数组和多重指针
- 动态内存分配
- 计算机内存储器地址的编码方法
欲学好指针类型,首先要知道计算机内存储器地址的编码方法。计算机内存储器里存储的信息都是由1和0构成的二进制数来表示,每一位二进制数位是表示信息的最小单位,计算机技术规定在内存储器里用八位二进制数位来存储信息,这八位二进制数位叫一个字节,即在内存储器里是以字节为单位存储信息的,如大写英文字母A,在内存储器里用01000001表示。把能表示八位二进制数的存储空间叫一个字节存储单元。
- 存储单元的地址
C语言中数据有基本类型(字符型、整型、长整型、实型、枚举型)、构造类型、指针类型等。不同数据类型在内存中存储时,占用的字节数不同,如字符型需要1个字节空间,整型需要2个字节空间,长整型需要4个字节空间等。把不同数据类型存储时需要的N个字节看成一个整体,叫一个存储单元。对字符型N=1,整型N=2,长整型N=4等。对1个字节构成的存储单元,其字节单元地址编号就是该存储单元的地址,对多个(N>=2)字节构成的存储单元,其低字节单元地址为该存储单元的地址,也叫存储单元的首地址。
- 指针类型
语言中的指针类型有指针常量和指针变量。指针常量简称为指针,即存储单元的地址。可以认为配置不同容量的内存,其指针值的范围是不同的,但都是从0起始的。每个存储单元的指针值都是固定不变的。指针变量就是用来存放指针的变量。指针变量是一种较特别的变量,它的值是一些特定的整数值,不是任何整数(如负整数)都可以存放到指针变量,指针变量与整数加减运算也不同于数学中的运算方法。指针变量也有自己的内存空间,空间的大小由编译器决定,在Turbo C 2.0下是2个字节,在Visual VC++下是4个字节。
- 变量的指针
在编译C语言程序时,要在内存为各种变量分配相应的存储单元,相应的变量名称对应着存储单元的首地址,这首地址就是变量的指针。可以将一变量的指针赋给一指针变量(存到指针变量代表的存储单元中),这时就说指针变量指向了该变量(也可以说指针变量指向了该变量表示的存储单元)。对存储单元的存取操作即可以用变量名,也可以通过指向该变量的指针变量来进行,这要用到指针运算符“*”
- 指针变量类型和它所指向的数据类型
指针变量的类型以声明它时其前面的“*”为标志,无论指针变量指向何种数据类型,它所占用的内存空间大小是一定的(如2个字节),这与其他数据类型的变量所占有的内存空间大小一定一样,所以指针变量的类型就是指针类型,与它所指向的数据类型无关。有资料把可指向不同数据类型的指针变量说成有整型指针(int*)变量、实型指针(float *)变量、字符型指针(char *)变量等,如果非要这样说,理解成指针变量可指向什么数据类型变量就叫什么数据类型指针变量为好,如 int *p;的声明p可以指向整型变量,说p是整型指针变量为好。
声明指针变量时,还要声明允许指针变量指向的数据类型,这由声明指针变量时“*”前面的“基类型”决定。指针类型加减整数运算时移动的位置大小由指向的数据类型来决定。指向同一种数据类型的不同指针变量间可以进行加减或大小比较运算,指向不同数据类型的指针变量不能进行加减运算或大小比较运算。指针变量一旦被“基类型”声明可指向某种数据类型,就不能再指向其他别的数据类型。
指针类型中的指针变量还可进行自增自减运算,而指针不能。指针变量既可以是左值,也可以是右值,指针只能是右值。由指针、指针变量与运算符构成指针类型表达式。下面说的“&”作为单目运算符时与一个变量结合就构成指针表达式,如&a,&p等,而“*”作为单目运算符只可与指针类型结合,构成指针类型指向的数据类型表达式,如有:
int *p,a,b; p=&a; b=*p; *p=10; *&a=20;
其中“b=p;”的p就是整型表达式,也是一个整型变量,&a是指针类型表达式,*&a是一个整形表达式,也是一个整形变量。
- “&”和“*”运算符
C语言中有“&:按位与运算符,是双目运算符,结合性是由左到右”和“&:取地址运算符,是单目运算符,结合性是由右到左”,有“:乘法运算符,是双目运算符,结合性是由左到右”和“:指针运算符,是单目运算符,结合性是由右到左(“*”在声明指针变量时也用到了)”。
对于取地址运算符&只能与一个变量结合构成指针类型表达式,如有变量name,则&name就得到变量name的指针。
对于指针运算符*,意义是“取其指向的内容”,这里说“取其指向的内容”不是指存储单元里存放的值,而是表示指针变量指向的变量。在有的书中说“例如:&a为变量a的地址,*p为指针变量p所指向的存储单元的内容(即p所指向的变量的值)[1]”,这种说法值得商榷。笔者认为用“*p代表指针变量p所指向的存储单元(即p所指向的变量)”的说法比较合适,更直接说
p是一个变量,因为p可以是左值。如下代码:
void main()
{int a,*p;
p=&a;
*p=10;
printf(“%d,%dn”,a,*p);
*&a=20;}
输出a和p的结果都为10,说明p与a等价。通过 *&a= 20;语句还可以改变a的值,也说明 &a与a等价,&a可以是左值。
- 数组的指针
C语言中的数组是一种线性构造型数据类型,特点是:
(1) 数组中数据元素是有序的。
(2) 数组中每一个元素都是具有相同数据类型的拥有不同下标的同名变量,每个元素用下标来访问。
(3) 数组在内存中按下标递增的次序在地址连续的一片内存区域中存放,最低的地址对应于第一个数组元素,最高的地址对应最后一个元素,程序运行中数组大小不可改变。
(4) 二维数组或多维数组可看成多重一维数组的结合。如二维数组可看成两个相结合的一维数组,即一维数组中的每个元素又是一个一维数组的数组名。
数组名表示数组的入口指针,每个数组元素的指针由取地址运算符&与每个元素构成指针表达式得到。
二维数组可看成由若干行,每行又由若干列元素组成的有序元素的集合。二维数组名表示数组的入口,指向第一行一整行,叫行指针,数组元素的指针指向每一个元素,叫列指针。其实一维数组名就是列指针,指向第一个元素,这也是一维数组与二维数组一个很重要的区别。行指针和列指针可以互相转换,用“&、”两个运算符可以达到转换的目的。“&”把列指针转成行指针,“”把行指针转成列指针,这种转换不改变指针值的大小,改变了指针变量的指向。例如有int
a[N][M];声明一个 N行M列的二维数组。a
是数组的入口指针,是行指针,a[0]、a[1]、a[2]是列指针,&a[0][0]是元素a[0][0]的指针,其中a、*a、&a[0]、a[0]、&a[0][0]的值相等,但a、&a[0]指向行,*a、a[0]、&a[0][0]指向列。a与&a[0]等价,a[0]与
&a[0][0]等价,*a与a[0]、&a[0][0]也等价。
对于二维数组的第i行有:a+i 与 &a[i]等价,*(a+i)与a[i]等价,但不能说a+i与a[i]等价,尽管它们的值相等,a+i是指向第i行的行指针,a[i]是指向第i行第0列元素的,即是指向a[i][0]的列指针。
二维数组中指向第i行第j列的指针可以是如下形式:&a[i][j]、a[i]+j和*(a+i)+j,对第i行第j列元素的存取可以用如下形式:a[i][j]、(a[i]+j)和(*(a+i)+j)。
a+i(i>=0)也相当于是指向第i行有M个元素的一维数组的指针。
a又相当一有N个指针元素的指针数组,a相当指向指针的指针,N个元素不是指针(下标)变量,而是指针[3-5]。
8用指针变量引用数组的元素
当指针变量指向数组时,可以用该指针变量引用数组的元素。
用指针变量引用一维数组的元素,既可以用指针法(这要用到“*”指针运算符),也可以用下标法(即把指针变量当成数组名),相对简单。
用指针变量引用二维数组的元素,相对复杂些,当指针变量指向数组时,既可以是指向行,也可以是指向列。当指针变量指向列,如果把指针变量当成数组名,就可以把二维数组当成一维数组来对待,一维数组元素的个数由二维数组的行数与列数的乘积得到。如下代码:
void main()
{int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
int (*p)[4];
p=a;
printf(“%dn”,*(*(p+1)+2));
printf(“%dn”,p[1][2]);
}
程序运行后输出a数组中a[1][2]元素的值。
void main()
{int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
int *p;
p=a[0];
printf(“%dn”,*(p+6));
printf(“%dn”,p[6]);
}
程序运行后也是输出 a[1][2]元素的值[3,6-7]。
指针与指针变量的概念,指针与地址运算符 指针C语言中,任何数据都会占用内存单元的。计算机内存的每个存储位置都对应唯一的存储地址,而变量名作为变量数据存储区域所取的名字,代表的是一个内存编号,而这个内存编号对于用户来说是未知的。如定义:int a=12。
变量名a代表某个内存单元,而变量值12则是这块内存单元里面的内容。在整个程序运行过程中,通过变量名来访问变量,变量名a所代表的这块内存单元不变,所改变的只是这块内存单元里面的值。
C语言也支持使用变量存储地址来对变量进行存取操作,要取得变量的存储地址,可使用取地址运算符&,如&a表示变量a的存储地址;而变量的存储地址就是指针。
指针变量指针类型就是C语言中用于表示存储地址的数据类型,而专门用来存放变量存储地址的变量则称为指针变量
格式:数据类型 *指针变量名。跟普通变量不同的是,所有指针变量占用的内存单元大小是一样的,前面的数据类型代表的是指针变量所指向变量的数据类型。如以下代码: int a,*b;//a是一个int型变量,b是一个指向int型数据的指针变量
b=&a;//代表b指向a
使用指针变量的例子
#include例子int main() { int a = 100, b = 10; //定义整型a,b,并初始化 int *pointer_1, *pointer_2; //定义指向整型数据的指针变量pointer_1,pointer_2 pointer_1 = &a; //把a的地址赋给指针变量pointer_1 pointer_2 = &b; //把b的地址赋给指针变量pointer_2 printf("a=%d,b=%dn", a, b); printf("*pointer_1=%d,*pointer_2=%dn", *pointer_1, *pointer_2); return 0; }
double *pd ; char *s1 , *s2 ;
在这里定义了三个指针变量pd、s1和s2,其中指针变量pd的基类型为double类型,在指针变量pd中,只能存放double类型变量的地址,指针变量s1和s2的基类型为char类型,在指针变量s1和s2中只能存放char类型变量的地址
int **p ;
以上是定义了一个指向指针的指针变量p,该指针变量p只能存放基类型为int类型的指针变量的地址。
int *pi , **p , k ;
指针变量的基类型的作用以上语句是在同一语句中,同时定义了指针变量pi、指向指针的指针变量p和变量k,这是允许的。
定义指针变量任何一个指针变量都是用于存放它所指向变量的地址,只要能存放地址就可以了,为何还要区别不同的基类型呢?
其原理是:不同的数据类型变量,C语言系统为它们开辟的存储空间的字节数是不同的,
定义指针变量与定义普通变量非常类似,不过要在变量名前面加星号*,格式为:
类型名 *指针变量名; 类型 * 指针变量名=初值表达式;
给指针变量赋值 使指针指向一个对象其中,指针变量名是标识符,指针变量名之前的符号“*”,表示该变量是指针类型的。而最前面的“类型”,表示该指针变量能指向变量或函数的类型。初值表达式是一个地址表达式,如表达式中有某变量的地址表达式,则这个变量应是前面已定义的。
- 通过求地址运算符(&)把一个变量的地址赋给指针变量
“&”是求地址运算符,该运算符为单目运算符,用于求变量的地址,且该变量必须为内存变量。
例如:
int k=1 , j =2 , *q1 , *q2 , *p ;
float x=4.5 ;
q1=&k ;
q2=&j ;
以上第三条语句,是把变量k的地址赋给了指针变量q1,使指针变量q1中存放了变量k的地址,或称指针变量q1指向了变量k。同理,以上第四条语句,是把变量j的地址赋给了指针变量q2,使指针变量q2中存放了变量j的地址,或称指针变量q2指向了变量j。
注意:在使用 & 运算符求变量的地址,并赋给指针变量时,一定要确保所求地址的变量数据类型与存放该变量地址的指针变量基类型一致。
- 同类型指针变量之间可以直接赋值
可以把指针变量的值赋给指针变量,但一定要确保这两个指针变量的基类型是相同的。
接上例:p=q1 ;
执行以上语句后,使指针变量p也存放了变量k的地址,也就是说指针变量p和q1同时指向了变量k
- 概念不同
“指针”是概念,“指针变量”是具体实现,指针也是一个变量,所以需要进行定义,而对于指针的定义,与一般变量一样。
- 存放地址不同
指针和指针变量的关系一个变量的(内存)地址称为该变量的“指针”,通过指针能找到以它为地址的内存单元。而指针变量是用来存放另一个变量的地址的(即指针)
-
指针就是地址,地址就是指针。
-
地址就是内存单元的编号。
-
指针变量就是存放内存地址的变量。
-
指针和指针变量是两个不同的概念,但要注意的是,通常我们叙述时会把指针变量简称为指针,实际他们含义并不一样。
注:
指针里存的是100. 指针:地址 - 具体。 指针里存的是地址,指针:指针变量 -可变。 指针的好处:
1、直接访问硬件
2、快速传递数据(指针表示地址)
3、返回一个以上的值返回一个(数组或者结构体的指针)
4、表示复杂的数据结构(结构体)
5、方便处理字符串
6、指针有助于理解面向对象
通过指针引用数组一个变量有一个地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。指针变量既然可以指向变量,当然也可以指向数组元素(把某一个元素的地址放在一个指针变量中)所谓数组的指针是指数组的起始地址,数组元素的指针是数组元素的地址。
可以用一个指针变量指向一个数组元素,例如:
int a[10] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
int *p;
p = &a[0];
C语言规定,数组名代表数组的首地址,也就是第0号元素的地址。因此,下面两个语句等价:
p=&a[0]; p=a;
在定义指针变量时可以赋给初值:
int *p=&a[0];
它等效于:
int *p; p=&a[0];
当然定义时也可以写成:
int *p=a;
从图中我们可以看出有以下关系:
p,a,&a[0]均指向同一单元,它们是数组a的首地址,也是0 号元素a[0]的首地址。应该说明的是p是变量,而a,&a[0]都是常量。在编程时应予以注意。
数组指针变量说明的一般形式为:
类型说明符 *指针变量名;
其中类型说明符表示所指数组的类型。从一般形式可以看出指向数组的指针变量和指向普通变量的指针变量的说明是相同的。
C语言规定:如果指针变量p已指向数组中的一个元素,则p+1指向同一数组中的下一个元素。
引入指针变量后,就可以用两种方法来访问数组元素了。
如果p的初值为&a[0],则:
- ) p+i和a+i就是a[i]的地址,或者说它们指向a数组的第i个元素。
- ) (p+i)或(a+i)就是p+i或a+i所指向的数组元素,即a[i]。例如,(p+5)或(a+5)就是a[5]。
- ) 指向数组的指针变量也可以带下标,如p[i]与*(p+i)等价。
根据以上叙述,引用一个数组元素可以用:
4. ) 下标法,即用a[i]形式访问数组元素。在前面介绍数组时都是采用这种方法。
5. ) 指针法,即采用*(a+i)或*(p+i)形式,用间接访问的方法来访问数组元素,其中a是数组名,p是指向数组的指针变量,其处值p=a。
【例1】输出数组中的全部元素。(下标法)
#includeint main(void) { int a[10], i; for (i = 0; i < 10; i++) a[i] = i; for (i = 0; i < 5; i++) printf("a[%d]=%dn", i, a[i]); }
【例2】输出数组中的全部元素。(通过数组名计算元素的地址,找出元素的值)
#include几个注意的问题:int main(void) { int a[10], i; for (i = 0; i < 10; i++) *(a + i) = i; for (i = 0; i < 10; i++) printf("a[%d]=%dn", i, *(a + i)); }
数组名作函数参数
- 指针变量可以实现本身的值的改变。如p++是合法的;而a++是错误的。因为a是数组名,它是数组的首地址,是常量。
- 要注意指针变量的当前值。
- 从上例可以看出,虽然定义数组时指定它包含10个元素,但指针变量可以指到数组以后的内存单元,系统并不认为非法。
- p++,由于++和同优先级,结合方向自右而左,等价于*(p++)。
- (p++)与(++p)作用不同。若p的初值为a,则*(p++)等价a[0],*(++p)等价a[1]。
- (*p)++表示p所指向的元素值加1。 7) 如果p当前指向a数组中的第i个元素,则
*(p–)相当于a[i–];
*(++p)相当于a[++i];
*(–p)相当于a[–i]。
#include
int main(void)
{
void fun(int arr[],int n); //对fun函数声明
int array[10]; //定义array数组
…
fun(array,10); 用数组名做函数的参数
return 0;
}
void fun(int arr[],int n)
{
…
}
}
f(int arr[],int n);
{
……
……
}
array为实参数组名,arr为形参数组名。在学习指针变量之后就更容易理解这个问题了。数组名就是数组的首地址,实参向形参传送数组名实际上就是传送数组的地址,形参得到该地址后也指向同一数组。这就好象同一件物品有两个彼此不同的名称一样。
同样,指针变量的值也是地址,数组指针变量的值即为数组的首地址,当然也可作为函数的参数使用。
【例3】将数组a中的n个整数按相反顺序存放。
算法为:将a[0]与a[n-1]对换,再a[1]与a[n-2] 对换……,直到将a[(n-1/2)]与a[n-int((n-1)/2)]对换。今用循环处理此问题,设两个“位置指示变量”i和j,i的初值为0,j的初值为n-1。将a[i]与a[j]交换,然后使i的值加1,j的值减1,再将a[i]与a[j]交换,直到i=(n-1)/2为止,如图所示。
#includevoid inv(int x[], int n) { int temp, i, j, m = (n - 1) / 2; for (i = 0; i <= m; i++) { j = n - 1 - i; temp = x[i]; x[i] = x[j]; x[j] = temp; } return; } int main() { int i, a[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2}; printf("The original array:n"); for (i = 0; i < 10; i++) printf("%d", a[i]); printf("n"); inv(a, 10); printf("The array has benn inverted:n"); for (i = 0; i < 10; i++) printf("%d", a[i]); printf("n"); return 0; }
对此程序可以作一些改动。将函数inv中的形参x改成指针变量
#include指向多维数组的指针和指针变量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; } return; } int main() { int i, a[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2}; printf("The original array:n"); for (i = 0; i < 10; i++) printf("%d", a[i]); printf("n"); inv(a, 10); printf("The array has benn inverted:n"); for (i = 0; i < 10; i++) printf("%d", a[i]); printf("n"); return 0; }
- 多维数组的地址
- 指向多维数组的指针变量
把二维数组a分解为一维数组a[0],a[1],a[2]之后,设p为指向二维数组的指针变量。可定义为:
int (p)[4]
它表示p是一个指针变量,它指向包含4个元素的一维数组。若指向第一个一维数组a[0],其值等于a,a[0],或&a[0][0]等。而p+i则指向一维数组a[i]。从前面的分析可得出(p+i)+j是二维数组i行j 列的元素的地址,而*(*(p+i)+j)则是i行j列元素的值。
二维数组指针变量说明的一般形式为:
类型说明符 (指针变量名)[长度]
其中“类型说明符”为所指数组的数据类型。“”表示其后的变量是指针类型。“长度”表示二维数组分解为多个一维数组时,一维数组的长度,也就是二维数组的列数。应注意“(*指针变量名)”两边的括号不可少,如缺少括号则表示是指针数组(本章后面介绍),意义就完全不同了。
C语言表示字符串的两种表示法一串以’ ’结尾的字符在C语言中被看作字符串
字符串常量是用双引号括起的以‘ ’结束的一串字符。
在程序开始运行时分配在全局数据区的文字常量区,存储在无名数组中。 相同字符串常量只有一个副本。
字符数组
字符指针
- 在C语言中,字符串是存放在字符数组中的,想引用一个字符串,可以用以下两种方法
- 用字符数组存放一个字符串,可以通过数组名和下标引用字符串中的一个字符,也可以通过数组名和格式声明“%s”输出该字符串
#include//用字符数组存放一个字符串,可以通过数组名和下标引用字符串中一个字符串中一个字符,也可以通过数组名和格式声明“%s”输出该字符。 int main() { char string[] = "I love China!"; printf("%sn", string); printf("%cn", string[7]); return 0; }
在栈中为string数组分配内存,"I love China!"看上去是字符串,其实是字符数组{‘I’,’ ‘,‘l’,‘o’,‘v’,‘e’,’ ‘,‘C’,‘h’,‘i’,‘n’,‘a’,’!’,’ ’}的简写形式
- 用字符串指针变量指向一个字符串常量,通过字符指针引用字符串常量
int main()
{
char *string = "I love China!";
printf("%sn", string);
return 0;
}
- 把存放字符串的无名数组的首地址赋给string。
- char *string = “I love China!”; 等价于:
char *string;
string = “I love China!”;
几种将字符型指针变量指向字符串的正确方法:char string[] = “I love China!”; 等价于: char string[20];
strcpy(string,“I love China!”);
“I love China!” 是常量字符串
const char *p; //p是指针变量,p指向的目标空间的内容不可变化 char * const p;
//p是指针常量,p的值不可变,但它指向目标的值可变
方法一:在定义字符型指针变量时为其赋初值一个字符串(初始化)。 char *p =“123”;
方法二: 先定义字符型指针变量,然后通过赋值语句让指针变量指向字符串。char *p;p =“123”;
实例中的字符串常量“132”,在程序中给出的是它在内存空间的首地址,因此可以通过赋值语句将这段无名储存区的首地址赋值给指针变量,使得指针指向该字符串。
方法三:先定义字符型指针变量,然后将指针变量赋一个有效的地址值(可以将指针赋值为一个字符数组的首地址,或者调用malloc函数为指针变量动态分配一段储存空间),最后调用strucy函数将字符串复制到指针所指向的这段存储空间,
char a[6],*p; char *p; p=a; p=(char*)malloc(3*sizeof(char)); strcpy(p,"123") strcpy(p,"123")
字符指针作为函数参数在使用strcpy函数之前,指针p必须指向一个有效的存储空间,然后存储空间内存放字符串常量。如果指针只是定义,没有为其赋有效的地址值,这样的指针是不能拿来用
1. 用字符数组名作参数例8.20 用函数调用实现字符串的复制
函数的形参和实参可以分别用字符数组名或字符指针变量
#include2. 字符型指针变量作实参void copy_stying(char from[], char to[]) { int i = 0; while ((from[i] = to[i]) != ' ') { ++i; } } int main() { char a[16] = "good good study"; char b[16] = "day day up"; char c[30]; copy_stying(b, a); copy_stying(c, "copy successfully"); printf("string a:%snstring b:%sn%sn", a, b, c); return 0; }
copy_stying函数不变,在main函数中定义字符指针变量from和to,分别指向两个字符数组a,b;
int main()
{
char a[16] = "good good study";
char b[16] = "day day up";
char *pa = a, *pb = b;
printf("string a:%snstring b:%snn", pa, pb);
copy_stying(pb, pa);
printf("string a:%snstring b:%sn%sn", pa, pb);
return 0;
}
3. 用字符指针变量作形参和实参
int main()
{
void copy_stying(char from[], char to[]);
char *a = "I am a teacher.";
char b[] = "You are a student.";
char *p = b;
printf("string a:%snstring b:%snn", a, b);
printf("ncopy stying a to string b:n");
copy_stying(a, p);
printf("string a:%snstring b:%sn%sn", a, b);
return 0;
}
void copy_stying(char from[], char to[])
{
for (; *from != ' '; from++, to++)
{
*to = *from;
}
*to = ' ';
}
//进一步简化 while (*from++ = *to++);//不推荐 等价于 while ((*from++ = *to++)!= ′0′); //推荐 //函数体中while语句也可以改用for语句: for (;(*from=*to)!=0;++from,++to);// 推荐 等价于 for (;*from++=*to++;);//不推荐
| 实参 | 形参 | 实参 | 形参 |
|---|---|---|---|
| 字符数组名 | 字符数组名 | 字符指针变量 | 字符指针变量 |
| 字符数组名 | 字符指针变量 | 字符指针变量 | 字符数组名 |



