一、字符指针、字符数组

字符指针

字符串指针变量本身是一个变量用于存放字符串的首地址。而字符串本身是存放在以该首地址为首的一块连续的内存空间中并以 作为串的结束。

char *ps="C Language";

顺序是1.分配内存给字符指针2.分配内存给字符串3.将字符串首地址赋值给字符指针

char *ps; // ps 字符串指针是指针是一个变量

ps="C Language"; // ps 为字符串的首地址利用 ps++ 可遍历字符串字符串存储在以 ps 为开始地址的地段连续的内存空间中并以 作为字符串的结束。

这里有两点需要考虑清楚的地方

1、*a 只是指向一个字符。

举例如下

实例

#include <stdio.h>#include <stdlib.h>int main(void){char *a= "bcd" ;printf("输出字符%c n", *a); /*输出字符使用"%c"*/printf("输出字符%c n", *(a+1) ); /*输出字符使用"%c"*/printf("输出字符串%s n", a); /*输出字符串使用"%s"而且a之前不能有星号"*" */system("pause"); /*为了能看到输出结果*/}

运行结果如下

输出字符b 输出字符c 输出字符串bcd 

2、若字符串常量出现在在表达式中代表的值为该字符串常量的第一个字符的地址。所以 hello 仅仅代表的是其地址。原声明方式相当于以下声明方式

char *a; a="hello"; /*这里字符串"hello"仅仅代表其第一个字符的地址*/

字符数组

字符数组是由于若干个数组元素组成的它可用来存放整个字符串。即用字符数组来存放字符串。

在 C 语言中将字符串作为字符数组来处理。C++中不是

字符数组初始化的方法

1). 可以用字符串常量来初始化字符数组

char str[]={"Iamhappy"};

可以省略花括号

char str[]="Iamhappy"; # 系统自动加入  

注意上述这种字符数组的整体赋值只能在字符数组初始化时使用不能用于字符数组的赋值字符数组的赋值只能对其元素一一赋值。

下面的赋值方法是错误的

char str[20];str="Iamhappy";

对字符数组的各元素逐个赋值。

char str[10]={'I','','a','m','',‘h’,'a','p','p','y'};

在 C 语言中可以用两种方法表示和存放字符串

1用字符数组存放一个字符串

char str[]="IloveChina";

2用字符指针指向一个字符串

char *str="IloveChina";

两种表示方式的字符串输出都用printf"%sn", str;

%s 表示输出一个字符串给出字符指针变量名 str对于第一种表示方法字符数组名即是字符数组的首地址与第二种中的指针意义是一致的则系统先输出它所指向的一个字符数据然后自动使 str 自动加 1使之指向下一个字符...如此直到遇到字符串结束标识符


二、字符串指针

string* str 可以赋值:

string* str = {"hello", "world"}; // 对比与 char *name = "wang" = {'w','a','n','g'}// *(str) = "hello", *(str+1) = "world"// *(*(str)+1) = 'e'

也就是说每个元素都是 string 类型的跟 char* 是不一样的不过 string* 可以用 char** 来代替:

string = char*, string* = char**

三、字符串指针数组

实例

#include <stdio.h>void main(){char *str[] = {"Hello", "C++", "World"}; //char (*str)[] = ...int i;for(i=0; i<3; i++)printf("%sn", str[i]);}// str[0]字符串"hello"的首地址str[0]+1字符串"hello"第二个字符'e'的地址str[2]=str+2:第三个字符串"world"的首地址// str[1]字符串"C++"的首地址// str[2]字符串"world"的首地址

实例

#include <stdio.h>#include <string.h>int main(){char *str[] = {"Hello", "C++", "World"};char **p;for(p=str; p<str+3; p++)puts(*p); #*p为字符串首地址*p[0]为字符串的第一个字符地址}

实例

#include<stdio.h>#include<stdlib.h>int main(){char *str[3]={"Hello","C++","World"};printf("%s,%s,%c",str[0],str[0]+1,*(*(str+2)+1));system("pause");}

结果为

Hello,ello,o

格式char* na[N] = {"li", "zh", "li", "zh", "li"};

char *a[]表示a是数组数组中的元素是指针指向char类型(数组里面所有的元素是连续的内存存放的)数组名是数组第一个字节的内存地址并且数组名a也表示指针。所以a 并不表示a地址存储的内容, 而是a地址本身。

a+1表示 a 的第二个元素的内存地址, 所以是加 8 字节。( 因为a的元素是char 指针, 所需要的空间为8字节(64位内存地址)。 )

*(a+1)则表示a这个数组的第二个元素的内容 (是个char 类型的指针本例表示为world字符串的地址)。

*(*(a+1))则表示a这个数组的第二个元素的内容(char指针)所指向的内容(w字符).

char * a[10]表示限定这个数组最多可存放10个元素(char指针), 也就是说这个数组占用10*8 = 80字节。

#w    a+1  =>  *(a+1) =>  *(a+1)[0]      指针(地址)  指针内容(字符串)   字符

char *argv理解为字符串char **argv理解为字符串指针char *argv[]字符串指针数组

int main(int argc, char*argv[])这是一个典型的数组名或者说是指针数组做函数参数的例子而且还是没有指定大小的形参数组。

有时为了再被调用函数中处理数组元素的需要可以另设一个形参传递需要处理的数组元素的个数。而且用数组名做函数实参时不是吧数组元素的值传递给形参而是把实参数组的首元素的地址传递给形参数组这样两个数组久共同占有同一内存单元。 和变量作函数参数的作用不一样。

可以去看看关于数组作为函数参数和指针数组作main函数形参方面的例子。谭浩强的那本书讲的很细对这个有详细的解释。

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[] 把内容存在stack。char *a 则把指针存在 stack把内容存在 constants。

3. char * a[10] 和 char a[10][20]

  • 相同点 : a 都是2级指针, *a 表示一级指针, **a 表示内存中存储的内容。
  • 不同点 : char * a[10], 数组由char * 类型的指针组成; char a [10][20] 表示一位放10个元素, 二维放20个元素, 值存放地是一块连续的内存区域, 没有指针。

4. 小窍门 : [] 和 * 的数量对应, 如 char a[][] 的指针层数是 2, 相当于 char **a; char *a[] 也是如此, 两层指针. 迷糊的时候数数到底有几个 * 几个 [], 就知道什么情况下存储的是内容还是地址了 ? 如 char a[][] 的情况里面: &a, a, *a 都是地址, **a 是内容。

原文地址https://www.cnblogs.com/cj2014/p/3726380.html