指针资料整理 (一)

2014-11-23 22:13:32 ? 作者: ? 浏览: 10

这些天笔试经常碰到指针的题目,故做了一个整理。

指针在应用中的各种类型:
(1) int *ip; //(char* cp,float* fp,double* dp) 一级指针变量
(2) int **ip; //(char** cp,float** fp,double** dp) 二级指针变量
(3) const int* ip; //常量指针
(4) int* const ip; //指针常量
(5) const int* const icp; //常量指针常量
(6) int *ip[10]; //指针数组
(7) int (*ip)[10]; //数组指针
(8) int *f(int a); //char* copy(char* s1, char* s2) 指针函数
(9) int (*gp)(int); //函数指针
(10) int (*gp[10])(int); //函数指针的数组

下面针对这11中情况作一一解说
(1) int *ip; //(char* cp,float* fp,double* dp) 一级指针变量
一级指针是我们接触最多,也是最简单的指针。
#include
using namespace std;

int main(void)
{
char *p = "hello world";
int i = 0;
while(p[i] != '\0')
cout << p[i++];
cout << '\n';

int *ip, iq;
iq = 5;
ip = &iq;
}
上面程序体现了二个问题:1)指针的增减运算 2)定义指针一个*只能修饰一个指针
指针的增减是以该类型的实体大小为单位的(但对指针作乘除是没有意义的)
对char指针加 1 实际增加了1个字节
对float指针加 1 实际增加了4个字节
对int指针加 1 实际增加了4个字节
定义指针一个*只能修饰一个指针
程序中的 ip是一个指针,而iq是一个整数变量

在很多c/c++程序,指针跟数组进行替换使用,这样以使得我们觉得指针跟数值是等价,但是数组跟指针还是有很大区别的,请看下面的例子。
#include
using namespace std;

void fun(char a[100])
{
cout << sizeof(a) << '\n'; //4
}

int main(void)
{
char a[] = "hello world";
a[0] = 'Y';
char *p = "welcome to c++";
// p[0] = 'X'; //编译器不能发现该错误,但是运行时出错
cout << sizeof(a) << '\n'; //12
cout << sizeof(p) << '\n'; //4
fun(a);
}

看了上面的例子之后,我们来说说数组跟指针的区别:
数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。
指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存。指针远比数组灵活,但也更危险。
字符数组 a 的容量是 12 个字符,其内容为 hello world\0。a 的内容可以改变,如 a[0]= ‘Y’。指针 p 指向常量字符串“welcome to c++”,(位于静态存储区,内容为 welcome to c++\0) ,
常量字符串的内容是不可以被修改的。从语法上看,编译器并不觉得语句 p[0]= ‘X’有什么不妥,但是该语句企图修改常量字符串的内容而导致运行错误,
所以我们经常把char *p = "welcome to c++" 写成 const char *p = "welcome to c++",这样就能够使得 p[0] = 'X'语句在编译的时候就报错。
sizeof(a)的大小是12(注意别忘了\0) sizeof(p)是一个指针的大小,当把数组作为函数参数进行传递时,数组自动退化为指针。

指针参数如何传递内存的
#include
#include
using namespace std;

char* getStr1()
{
char a[] = "hello world";
return a;
}

char* getStr2()
{
char *a = new char[12];
strcpy(a, "hello world");
return a;
}

char* getStr3()
{
char *a = "hello world";
return a;
}

void getStr4(char *p, int num)
{
p = new char[num];
strcpy(p, "hello world");
}

void getStr5(char **p,int num)
{
*p = new char[num];
strcpy(*p, "hello world");
}
int main(void)
{
cout << "getStr1 " << getStr1() << '\n';

char *str2 = NULL;
str2 = getStr2();
cout << "getStr2 " << str2 << '\n';
str2[0] = 'X';
cout << "getStr2 " << str2 << '\n';
delete [] str2;
char *str3 = NULL;
str3 = getStr3();
cout << "getStr3 " << str3 << '\n';
// str3[0] = 'X'; //编译通过,但运行出错

char *str4 = NULL;
int num = 50;
getStr4(str4, num);
cout << "getStr4 " << (str4 == NULL "NULL": str4) << '\n';

char *str5 = NULL;
getStr5(&str5, num);
cout << "getStr5 " << str5 << '\n';
}

getStr1()输出的是乱码,因为在getStr1()里return的是栈内存,所以当退出函数之后,char a[]也随着被清除了。
getStr2()能够正确运行。
getStr3()虽然能够正确运行,但是不管在什么地方返回都是常量数据
getStr4()运行结束后,str4仍然还是NULL,因为char *p参数在getStr4()函数运行结束后随着也被清除了
getStr5()能够正确运行。

(2) int **ip; //(char** cp,float** fp,double** dp) 二级指针变量
二级指针变量与一级指针变量的关系,跟二维数组与一维数组的关系有些类似,在这就不多说了


(3) const int* ip; //常量指针
(4) int* const ip; //指针常量
(5) const int* const icp; //常量指针常量
这3个有一些相似性,看如下例子。
#include
using namespace std;

int main(void)
{
const int a = 10;
int b = 5;
int c = 13;
const int *ip = &a;
int* const cp = &b;
const int* const icp = &c;

*ip = 30; //错误,常量指针不能修改指向的常量,*ip只能做右值
ip = &c; //正确,指针本身能够改变
*cp = 50; //正确,指针常量,指针所指向的值能够修改
cp = &c; //错误,指针常量本身不能够改变
*icp = 50;//错误,常量指针常量不能修改指向的常量
icp = &c; //错误,常量指针常量不能够改变指针本身
}

(6) int

-->

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: