一、字符指针、字符数组
1. 字符指针:字符串指针变量本身是一个变量,用于存放字符串的首地址。而字符串本身是存放在以该首地址为首的一块连续的内存空间中并以‘\0’作为串的结束。
char *ps="C Language"; 顺序是:1.分配内存给字符指针;2.分配内存给字符串;3.将字符串首地址赋值给字符指针;
可以写为:
char *ps; #ps字符串指针,是指针,是一个变量,
ps="C Language"; #ps为字符串的首地址,利用ps++可遍历字符串,字符串存储在以ps为开始地址的地段连续的内存空间中,并以'\0'作为字符串的结束。
这里有两点需要注意:
①定义字符指针char *a中,*a只是指向一个字符。举例如下:
#include
int main(){
char *a="bcd" ;
printf("输出字符:%c
",*a); //输出字符
printf("输出字符:%c
",*(a+1)); //输出字符/
printf("输出字符串:%s
",a); //输出字符串
}
运行结果如下:
②若字符串常量出现在在表达式中,代表的值为该字符串常量的第一个字符的地址。
char *a; a="hello";
这里字符串"hello"仅仅代表其第一个字符的地址。
2. 字符数组:字符数组是由于若干个数组元素(一个个字符)组成的,它可用来存放整个字符串。(即用字符数组来存放字符串)。
在c语言中,将字符串作为字符数组来处理。(c++中不是)
字符数组初始化的方法:
1). 可以用字符串常量来初始化字符数组:char str[]=; //可以省略花括号
char str[]="Iamhappy"; //系统自动加入‘\0’
注意:上述这种字符数组的整体赋值只能在字符数组初始化时使用,不能用于字符数组的赋值,字符数组的赋值只能对其元素一一赋值。
下面的两种赋值方法都是错误的:
char str[20];
str="Iamhappy";
对字符数组的各元素逐个赋值:
char str[20]
str[8]={'I','','a','m','',‘h’,'a','p','p','y'};
在C语言中,可以用两种方法表示和存放字符串:
(1)用字符数组存放一个字符串
char str[]="IloveChina";
(2)用字符指针指向一个字符串
char *str="IloveChina";
两种表示方式的字符串输出都用:printf(“%s
”, str);
%s表示输出一个字符串,给出字符指针变量名str(对于第一种表示方法,字符数组名即是字符数组的首地址,与第二种中的指针意义是一致的),
则系统先输出它所指向的一个字符,然后使str自动加1,使之指向下一个字符...,如此,直到遇到字符串结束标识符"\0"。
二、(字符串)指针数组
#include
void main()
{
char *str[]=;
int i;
for(i=0; i<3; i++)
printf("%s
", str[i]);
}
或
#include
int main(){
char *str[]=;
printf("%s,%s,%s
",str[0],str[0]+1,*str);
printf("%c,%s,%c,%c,%s
",**str,*str+2,*str[2],**(str+2),*(str+2));
}
运行结果为:
其中,str[i]为数组中第i+1个字符串的首地址,*str为数组第一个字符串的首地址,也即数组第一个字符串的第一个字符的地址,*str+i为数组第一个字符串中第i+1个字符的地址,
str[i]+j为数组第i个字符串中第j+1个字符的地址,str[k]=*(str+k)为数组中第k+1个字符串的首地址。
或
#include
int main()
{
char *str[]=;
char **p;
p=str;
printf("%c,%c
",*p[0],*(p[2]+1));
for(; p
printf("%s
",*p);
}
运行结果为:
其中,p为char类型指向指针的指针,第一个指针p包含了第二个指针*p的地址,第二个指针*p指向包含实际值的位置。
p[i]找到字符数组中第i+1个字符串,并指向第i+1个字符串的首地址;*p[i]做取值操作,p[i]+j为数组第i个字符串中第j+1个字符的地址。
总的来说,对于char *a[],a是数组,数组中的元素是指针,指向char类型,(数组里面所有的元素是连续的内存存放的);
数组名是数组第一个字节的内存地址,并且数组名a也表示指针。所以a 并不表示a地址存储的内容, 而是a地址本身。
a+1 表示数组第二个字符串的地址;
*(a+1) 则表示a这个数组的第二个字符串的首地址 (是个char 类型的指针);
*(*(a+1)) 则表示a这个数组的第二个字符串首地址(char指针)所指向的内容,即数组第二个字符串中的第一个字符;
char * a[10] 表示限定这个数组最多可存放10个字符串(char指针)。
三、
char *argv:理解为字符串
char **argv:理解为字符串指针
char *argv[]:字符串指针数组
1. 当char []作为函数的参数时, 表示 char *。当作为函数的参数传入时, 实际上是拷贝了数组的第一个元素的地址;
所以 void test (char a[]) 等同于 void test ( char * a );
char x[10];然后调用 test(x) 则等同于把 x 的第一个元素的地址赋予给参数 a;
2. char * a 和 char a[]
相同点 : a都是指针, 指向char类型.
不同点 : char a[] 把内容存放于栈中,char *a 则把指针存放在栈,把内容存放在内存中 。
3. char * a[10] 和 char a[10][20]
相同点 : a 都是2级指针,*a 表示一级指针, **a 表示内存中存储的内容。
不同点 : char * a[10], 数组由char * 类型的指针组成,限定这个数组最多可存放10个元素(char指针)
char a [10][20] 表示有10行、20列元素的矩阵,值存放地是一块连续的内存区域, 没有指针。
4. 小窍门 : []和*的数量对应, 如 char a[][]的指针层数是2, 相当于char **a; char *a[]也是如此。
两层指针迷糊的时候数数到底有几个*几个[], 就知道什么情况下存储的是内容还是地址了。 如char a[][] 的情况里面: &a, a, *a 都是地址, **a 是内容.