有关c/c++指针的金典问题
参考一:
有关C/C++指针的经典面试题
C语言为何如此长寿并实用?C++为什么有那么多精彩?指针可以说是C/C++中的灵魂所在,虽然早期中pascal也有指针,但是和C/C++比起来不是一个级别的.今天为大家深入浅出的解析一下指针的有关笔试,面试题.所有题目来源网络,分析是我写的... |
0.预备知识,最基础的指针
其实最基础的指针也就应该如下面代码:
int a;
int* p=&a;
也就是说,声明了一个int变量a,然后声明一个int 的指针,*p指向a的地址,&也就是取地址符号,而*是指针中取内容的符号,仅仅在声明的时候标记这个变量是指针.可能有点绕口,但是看代码来的容易的多...
1.与const在一起的时候
常常声明的时候会让人一头雾水,比如下面的声明,均是声明一个char* p的指针:
char * const p; // 指针不可改,也就说指针只能指向一个地址,不能更改为其他地址
char const * p; // 所指内容不可改,也就是说*p是常量字符串
char const * const p; // 内容和指针都不能改
const char * const p; // 同上...内容和指针不能改
额...别晕,别晕....其实方法很简单...你别真死记硬背...其实可以以*为分界符,在*左边有const就说明内容不能改,在*右边就说明指针不能改,而左边的char和const顺序是不要紧的...呵呵...你也可以理解成const是修饰后面的,正常顺序应该这样:const char * const p; 是不是看起来简单了?
2.忽悠人的陷阱,str[]和*str的区别
先告诉你哦,下面的题目可是陷阱啊....说说程序结果...
char str1[] = “abc”;
char str2[] = “abc”;
const char str3[] = “abc”;
const char str4[] = “abc”;
const char *str5 = “abc”;
const char *str6 = “abc”;
char *str7 = “abc”;
char *str8 = “abc”;
cout << ( str1 == str2 ) << endl;
cout << ( str3 == str4 ) << endl;
cout << ( str5 == str6 ) << endl;
cout << ( str7 == str8 ) << endl;
怎么样?都输出true?那显然你中标了...而且cout输出bool值的时候,就算全是真也应该都输出1啊...4个1?那也不对...答案是0011,不信你试试...为什么呢?
其实都说了这题是个大陷阱,因为这题根本不是比较字符串内容!而是比较字符串的地址.哦...恍然大悟...那为什么前两个是假呢?因为这可是说是一个深拷贝/浅拷贝的问题.当字符串是数组形式声明并初始化,编译器认为是新数组,分配新空间,但不是深拷贝,因为根本就不算拷贝.而如果是相同的字符串,用指针声明,那就是比较如果有一样的字符串,就直接把新指针指过去,这是正宗的浅拷贝.哇哈...你就中计了...
3.str[]用sizeof判断会出错么?
应该说我们常常用指针有很多时候是解决字符串的问题,一般我们用strlen,这当然没有问题,但是要你编一个呢?看看下面这个MyStrlen有问题么?
int MyStrlen(char str[])
{
return (int)(sizeof(str)-1);
}
呵呵...咱们上当过一次..这个当然也是不对的...不错...这个函数是错的...为什么呢?
首先,可以告诉你,无论何时,返回的总是3...额...是不是很奇怪,为什么不是数组长度呢?str不是char数组指针么?不错...确实是数组的指针,但是,当用函数传递的数组指针的时候就自动退化为指针了,而指针的长度是4,你减去1了自然就是3了.但是如果按照下面代码就可以得到正常的值.
char str[]="hello world";
int len=sizeof(str)-1; //记得减1哦,最后有'\0'结尾
cout<<len;
这样输出的是正常值,也就是你所希望的11;
4.注意数组指针和指针
继续上面的话题,刚刚提到了数组指针和指针,现在看看下面这端程序代码:
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);
cout<<*(a+1)<<*(ptr-1);
呵呵...BaihowFF总是给陷阱..肯定不是想当然的说就是21...确实...答案是25...额...奇怪吧..为什么呢?
首先,a是一个数组,所以编译器解释&a就是a的全部长度,就是说(&a+1)也就是说移动了一个数组,指向了并不存在的a[5],所以ptr-1才会指向a数组的最后一个元素a[4],而a+1和a[1]是一样的...所以答案是25,如果你去掉了(&a+1)的括号,那么答案就是想当然的21了...呵呵...很微妙吧....
5.注意指针要分配给足够的空间
新手在刚刚接触指针的时候经常会忘记给指针分配空间,直接用肯定是有问题的,那么下面的程序呢?
char a;
char *str=&a;
strcpy(str,”hello”);
cout<<str;
BaihowFF是坏蛋..总会下套...呵呵..确实是圈套...这段程序能够输出hello,但是输出后就崩溃了...原因就在你分配str指针的时候仅仅给了1字节的空间,但是你拷贝了6字节过去(不要忘记了最后的'\0'结束).运行输出后程序因为访问了没有分配的呵呵空间,当然崩溃了.如果你只strcpy(str,"");那程序是可以正常运行的.
6.小心编译器的指针字符串初始化
经常我们想自己处理字符串,但是像下面的初始化是很危险的!!!
char* s="AAA";
cout<<s<<endl;
s[0]='B';
cout<<s<<endl;
你可以拿这段程序去编译...没错!编译器报告正常!...这是最要命的...其实程序不能运行的...输出AAA后就崩溃了..为什么?因为当你在第一句初始化的时候,编译器就认为这是个字符串常量了...再做数组操作的时候肯定错了罗...最好的习惯是声明一个指针,用new分配空间,然后用库函数操作,比如strcpy,strcat等等...
7.让人一眼看上去迷糊的函数指针
看看这句代表什么意思?
int (*s[10])(int);
咦...这是什么?其实这是一个函数指针数组,指向了一组int fun(int)的函数,第一眼确实让人有点迷糊...但是请习惯这样...
8.注意函数传递指针的时候是副本
副本?又下副本?...汗...老兄...不是这个意思...别沉浸在WOW里了啊...看看下面程序的问题:
void GetMemory(char *p)
{
p=new char[100];
strcpy(p,"hello world");
}
void main(void)
{
char *str=NULL;
GetMemory(str);
cout<<str;
delete []str;
str=NULL;
}
当然了..喜欢下套的BaihowFF又给了错程序....错在哪呢?看上去是对的,而且编译器编译也正确啊..怎么就是不能通过呢?而且还崩溃了...好费解吧...
其实原因很简单...GetMemory这个函数出问题了!函数参数是不能传递分配空间的...因为传递过去实际上是一个副本p...不能返回的...而且你在delete那就是件很危险的事情..因为压根没有内容...那我实在想这样用函数分配怎么办呢?像下面这样改一下就ok了:
void GetMemory(char **p) // 改成晦涩难懂的指针的指针
{
*p=new char[100]; //给*p的分配地址
strcpy(*p,"hello world"); // 拷贝内容到*p
}
void main(void)
{
char *str=NULL;
GetMemory(&str); //这地方取地址
cout<<str;
delete []str;
str=NULL;
}
这样就能正常工作了,但是看起来好别扭啊...嗯..确实...但是还可以用其他方法哦....你想想...肯定有办法的...
9.请时刻记住要初始化字符串
嗯...这点大家都知道...那你猜猜下面的程序结果是多少?
char a[10];
cout<<strlen(a)<<endl;
答案应该让你以外...竟然是15...没道理吧?!其实strlen函数的结果和是否初始化有关的...虽然你分配了空间..但是没有初始化..库函数会出错的..sizeof不受影响...切忌初始化哦....
10.小括号,大区别
看看这两端声明,有什么不同?我直接在注释里告诉你答案吧...这样好看点...
char (*str)[20]; //str是一个数组指针,即指向数组的指针.
char *str[20]; //str是一个指针数组,其元素为指针型数据.
千万别小看括号哦...区别大了吧....
参考二:
c语言面试题__指针篇
|
有关c/c++指针的金典问题相关推荐
- kof97 逆向分析_指令输入系统
I/O 指令输入系统 1.在主循环中通过0x30000和0x340000找到0x9F68 0x9F68 翻译 UpdateP1P2KeyState 0x9F68是从IO的0x300000.0x3400 ...
- MIT 6.s081学习笔记
MIT 6.s081学习笔记 introduction 计算机组织结构: 最底部是一些硬件资源,包括了CPU,内存,磁盘,网卡 最上层会运行各种应用程序,比如vim,shell等,这些就是正在运行的所 ...
- 程序员面试金典 - 面试题 02.08. 环路检测(快慢指针)
1. 题目 给定一个有环链表,实现一个算法返回环路的开头节点. 有环链表的定义:在链表中某个节点的next元素指向在它前面出现过的节点,则表明该链表存在环路. 示例 1: 输入:head = [3,2 ...
- 程序员面试金典 - 面试题 02.06. 回文链表(快慢指针+链表反转)
1. 题目 编写一个函数,检查输入的链表是否是回文的. 示例 1: 输入: 1->2 输出: false 示例 2: 输入: 1->2->2->1 输出: true 进阶: 你 ...
- 剑指Offer - 面试题22. 链表中倒数第k个节点(快慢指针)
1. 题目 输入一个链表,输出该链表中倒数第k个节点.为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点.例如,一个链表有6个节点,从头节点开始,它们的值依次是1.2.3.4.5 ...
- 《程序员面试金典》+《算法导论》
<程序员面试金典>+<算法导论> 因为最近可能会面临一波面试,但是自己各种算法以及常见的问题的熟悉程度感觉还不够,但是由前几次的代码优化经验来看,算法优化可以说是代码优化的重中 ...
- 【重点】程序员面试金典——17.13树转链表
程序员面试金典--17.13树转链表 在<剑指offer>上有一个类似的题目:https://blog.csdn.net/allenlzcoder/article/details/7961 ...
- [转]《Python编程金典》读书笔记
<Python编程金典>读书笔记 原文: http://man.chinaunix.net/develop/python/python_howto/python_howto_program ...
- 《Python编程金典》读书笔记
<< Back to man.ChinaUnix.net <Python编程金典>读书笔记 整理:Jims of 肥肥世家 <yjnet@21cn.com> 第一次 ...
最新文章
- 新手必看:Python 3.8六大新功能
- sdut 2506 完美网络(优先队列)
- 看完Andoird9.0 Pie的隐藏特性,我买了SSL证书
- 将Python脚本打包成可执行文件
- CSS中属性个属性值怎么区分,[CSS] 详细解释 @media 属性与 (max
- nagios(icinga)借助check_hp插件监控惠普服务器硬件信息
- 简洁/易用/灵活/高效-RecyclerView适配器封装
- ETL介绍与ETL工具比较
- Numpy之数据清洗功能
- 一元二次方程组求根问题
- 常用下载方式的区别-BT下载、磁力链接、电驴
- 使用 X-Frame-Options 防止被iframe 造成跨域iframe 提交挂掉
- 王心凌的「爱你」,我们用Python跳起来!
- (五十二):多模态情感分析研究综述_张亚洲
- 怎么正确理解股票量化的概念?
- 170617 逆向-CrackMe之024
- Is necessary to close fille in python?
- Python吴恩达深度学习作业24 -- 语音识别关键字
- 分布式和集群的概念区别
- 介词 before behind before beside between