首先正确理解一下例子。
void test(){
char *str[]={"welcome","to","fortemedia","Nanjing"};
char * * p=str+1; //p指向 "to"字符串地址
printf("%s\n",str[0]);
printf("%s\n",str[1]);
printf("%s\n",str[2]);
printf("%s\n",str[3]);
printf("p==%x\n", p);
printf("str[0]==%x\n", str[0]);
printf("str[1]==%x\n", str[1]);
printf("str[2]==%x\n", str[2]);
printf("str[3]==%x\n", str[3]);
printf("**str==%x\n", &str);
printf("*p=%s\n", *p);
str[0]=(*p++) +2; //str[0]指向'\0'; 然后p后移 p=str[2]
str[1]=*(p+1); //p+1后 p+1 = str[3]; 然后 str[1] = str[3]
str[2]=p[1]+3; //str[2]指向str[3]的从0开始数的第三个 str[2]指向"jing"地址
str[3]=p[0]+(str[2]-str[1]); //str[3]指向从p[0]开始(也就是*p,也就是str[2])的 偏移量为(str[2]-str[1])的地址~ str[2]指向"jing",str[1]指向str[3],也就是"Namjing",所以str[3]指向"jing"的"g"地址
printf("%s\n",str[0]);
printf("%s\n",str[1]);
printf("%s\n",str[2]);
printf("%s\n",str[3]);
}
main函数中首先定义
char *p[DATA_LENGTH] ; // 定义一个指针数组。
char name[23] = "tian";// 定义一个字符数组。
init_data(p); // 初始化指针数组
printf("init done\n");
show(p);// 初始化指针数组的数组
printf("show done0==%s\n",p[0]);// p[0] 可以看作是数组的第一个数据。
CountStrLen(p[0]);// 计算初始化数组的第一个数据的字符串长度
void init_data(char **p){ // 参数传入二维指针
int i;
for(i =0;i< DATA_LENGTH;i++)
{
printf("init data==%d\n",i);
if(NULL==(p[i]=(char*)malloc(sizeof(char)*10))) // 循环遍历动态申请空间
{
perror("error...");
exit(1);
}else
{
memset(p[i],0,sizeof(char)*10); // 初始化数组的值为0
printf("init data==%s\n",p[i]);
}
}
}
正确的做法(这个函数有冗余代码)
void show(char **p){ // 参数传入二维指针
int i;
for(i = 0;i<DATA_LENGTH;i++){
char *tmp;
printf("show i==%d\n",i);
if(NULL != (tmp=(char*)malloc(sizeof(char)*10)))
{
memcpy(tmp,"tian",5); // 将tmp指向 tian 字符串的首地址
memcpy(p[0],tmp,5); // 给p[0] 所指的数据空间赋值为 “tian”
free(tmp); // 释放临时空间,切记,malloc 和free 一定同时出现
printf("the data%d==,%s\n",i,p[i]);
}
}
错误的做法
void show(char **p){ // 参数传入二维指针
int i;
for(i = 0;i<DATA_LENGTH;i++){
char *tmp;
printf("show i==%d\n",i);
if(NULL != (tmp=(char*)malloc(sizeof(char)*10)))
{
*tmp =“tian”;// 本身定义常量字符串他就是一段地址,也就是后期不能做修改。
p[i] =tmp; // 将p[i] 又指向了一段常量地址。
free(tmp); // 释放临时空间,切记,malloc 和free 一定同时出现
printf("the data%d==,%s\n",i,p[i]); // 打印没有问题,p[i] 一直是 tian
}
}
size_t CountStrLen(char *p){
int i;
size_t lenth=0;
printf("p==%s\n",p);
for(i =0 ; *p != '\0' ;i++){
p++;
lenth++;
printf("length==%d,p[i]==%s\n",lenth,p);
}
printf("length==%d\n",lenth);
return lenth;
}
总结:
1. 指针所指向的内存地址空间,需要memcpy ,strcpy 去初始化。
2. 在错误的方法中在main 打印p[0] 没有错,他打印的是“tian”字符串,只能是巧合,凑巧申请的。
3. 全局的指针指向了一个局部的地址空间,当函数运行结束,局部的地址空间被释放,所以全局的指针指向了一段被释放的地址空间。
4. 以后若使用赋值,采用memcpy ,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。