c/c++语言 指针赋值问题

来源:互联网 发布:炉石传说盒子大数据 编辑:程序博客网 时间:2024/05/29 13:29

昨天遇到一个指针赋值问题,一开始看代码好像没有错误,而且编译也通过了,运行确错误了,这不很奇怪吗?比如下面这个例子:

#include <stdio.h>

int main(void)
{
int j;
char *ch1[4] = {"hello", "hi", "ok", "yes"};
char *ch2[4] = {"HELLO", "HI", "OK", "YES"};
char **p1;
*p1 = ch1[1];
printf("%s\n", *p1);
return 0;
}

这个例子够简单吧。

初略分析下:

p1是一个指针,该指针的类型是char **,该指针指向的类型是char *;

*p1也是一个指针,该指针的类型是char *,该指针指向的类型是char。

而ch1是一个4元数组,该数组中存放的是指向char类型的指针。

若把ch1当做指针来看,那么ch1的类型是char **,ch1指向的类型是char *;*ch1等价于*(ch1+0)也等价于ch1[0],那么ch1[0]是什么呢?刚说过了,ch1是一个存放指针的4元数组,所以,ch1[0]存放的是"hello"的首地址,即字符h的地址。

这样一来,ch1[0]指针的类型是char *,该指针指向的类型是char。

看来指针*p1和ch1[0]的类型相同,他们指向的类型也相同,把ch1[0]赋值给*p1当然没问题了。那么程序为什么还出错呢?

仔细分析下便知道,其实p1是一个野指针,因为p1根本就没有初始化,它的地址是不确定的,也许这个地址是不能使用的。所以程序会出错。

给成如下形式便ok了:

#include <stdio.h>

int main(void)
{
int j;
char *ch1[4] = {"hello", "hi", "ok", "yes"};
char *ch2[4] = {"HELLO", "HI", "OK", "YES"};
char **p1 = ch2;
*p1 = ch1[0];
printf("%s\n", *p1);
return 0;
}

运行下,结果出来了吧。程序在声明初始化指针p1的时候,把ch2的地址赋给了p1,那么*p1指向了ch2[0]所在的内存区。执行了语句*p1=ch1[0]后,指针ch2[0]不在指向"HELLO"而是指向"hello"了,你可以用循环语句输出结果看看:

#include <stdio.h>

int main(void)
{
int j;
char *ch1[4] = {"hello", "hi", "ok", "yes"};
char *ch2[4] = {"HELLO", "HI", "OK", "YES"};
char **p1 = ch2;
*p1 = ch1[0];
for(j = 0; j < 4; j++)
   printf("%s\n", *p1++);
return 0;
}

关于指针赋值总结下:

1. 指针的赋值

int a = 4;

int *ptr = &a; //指针声明并初始化赋值

上面这一句等价于:

int *ptr;

prt = &a;

2. 以下是错误的赋值

int *ptr = 4;

或者

int *prt;

*ptr = 4;

因为此时的ptr是个野指针,ptr所指向的地址不确定。

3. 下面的赋值却是正确的

int *ptr = "hello";

或者

int *ptr;

ptr = "hello";

因为编译器将数组或者字符串解析为地址,编译时编译器将字符串存储在静态存储区。

在第一个声明中,看上去初始值是赋给表达式*prt的,事实上它是赋给ptr本身的。在字符串表达式中,表达式所使用的值就是这些字符所存储的地址,而不是这些字符本身。从第二种赋值方法中我们也可以明白这一点。

0 0