首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

C++有关问题集合

2012-02-06 
C++问题集合。最近遇到的一些问题想把它们彻底弄清楚。麻烦大大们了!1.关于数组越界问题首先看下面的一段代

C++问题集合。
最近遇到的一些问题   想把它们彻底弄清楚。麻烦大大们了!
1.   关于数组越界问题  
    首先看下面的一段代码
int   arr   [5]   =   {0,1,2,3,4};
int*   pt   =   arr;
pt   =   pt   +2;
cout   < <   pt[0];      
//运行以后显示的是2;
//运行以后   p[0]   =   2   p[1]   =   3   p[2]   =4
为什么p[3]   不等于0呢  
很显然p[3]以近越界了,它可能显示任何一个直,当然以后严格的编译系统会显示错误。
但是  
pt   =   pt   -2;
运行后p[0]     =   3
pt   [0]没越界吗?
难道是巧合?还是指针pt跳到了   显示   3的地址?
                0         1           2         3           4
地址       100     104       108     112       116
我画了一个图
//默认   int   占4字节  
要是pt   =   pt   -2的话
因该是   地址为   092的内存   但是092什么都没有储存啊?
这个时候   pt[0]越界了吗?

2.   接上面一个问题的图纸
                0         1           2         3           4
地址       100     104       108     112       116
图上面表示   100   104   108都分别储存了   0     1     2
我想问一下   那么地址   101   102   103   105等等会用来做什么?
被舍弃掉了吗?   还是用来储存其他非数组之类连续性的变量?


3.     switch语句中的默认语句   可有可无吗?

4.     关于cin  
见下面一段代码
int   golf[5];
for   (int   i   =   0;   i   <   5   ;   i++)
{
        cout   < <   "round   # "   < <(i+1)   < < ":   ";
        while   (!(cin> > golf[i]))  
        {
            cin.clear   ();       //   重直input
            while   (cin.get   ()!= '\n ')
            continue;               //清除错误的input
            cout   < <   "Please   enter   a   number "
          }
}

上面一段代码表示的   输入一个数组的个项
当为数字的时候通过并储存在golf[i]里面。
当输入字母的时候,提示 "Please   enter   a   number "   并重新输入一个数字

我想请问   为什么需要重置?   既然输入的是个字母,没有被储存在golf[i]里面,那就应该可以继续输入啊~我觉得   cin.clear   ();有点多余。。



[解决办法]
1:越界也只是针对array说的,你定义pt,编译器又不知道你想干什么,当然不会提示越界。
你对地址的想法是正确的,=3应该是个巧合,你可以尝试给那个地址赋个值,再操作下看看。
2:int类型占用的就是4个字节,只不过高位地址的值在你这里是0x00
3:没有可以,但是不是好的风格

[解决办法]
我觉得 cin.clear ();有点多余。。
=================
因为输入字母的时候,
cin 输入流的输入标志被 置位,
表示输入流发生错误,
那么之后 cin 将保留这个错误标志,
导致后续输入不起任何效果。

cin.clear ();
就是为了清除这个错误标志,
从而可以继续输入 ...
[解决办法]
1. 关于数组越界问题
首先看下面的一段代码
int arr [5] = {0,1,2,3,4};
int* pt = arr;
pt = pt +2;
cout < < pt[0];


//运行以后显示的是2;
//运行以后 p[0] = 2 p[1] = 3 p[2] =4
为什么p[3] 不等于0呢
很显然p[3]以近越界了,它可能显示任何一个直,当然以后严格的编译系统会显示错误。
但是
pt = pt -2;
运行后p[0] = 3
pt [0]没越界吗?
难道是巧合?还是指针pt跳到了 显示 3的地址?
0 1 2 3 4
地址 100 104 108 112 116
我画了一个图
//默认 int 占4字节
要是pt = pt -2的话
因该是 地址为 092的内存 但是092什么都没有储存啊?
这个时候 pt[0]越界了吗?


pt=pt-2之后,pt 指向的位置一定是越界了,跑到了数组的前面,这时对它取 pt[0]所得的数应该是随机的。虽然楼主取到了一个还算正常的数,但不意味着这种做法是正确的


2. 接上面一个问题的图纸
0 1 2 3 4
地址 100 104 108 112 116
图上面表示 100 104 108都分别储存了 0 1 2
我想问一下 那么地址 101 102 103 105等等会用来做什么?
被舍弃掉了吗? 还是用来储存其他非数组之类连续性的变量?


当然没有舍弃,因为一个int占四个字节,每个字节八个二进制位,那么相当于32位,而这32位都用来存每个int的0,1表示,之所以会出现100 104这样的跳跃存储,正是因为102 103都已经存满了,101 104只不过是一个新的int的存储地址的首地址而已


3. switch语句中的默认语句 可有可无吗?

default语句通常是一个错误出口,例如你要判断键盘上输入的字母是A-Z中的哪一个,而这时用户输入了一个数字9,这就要用default来处理。因为你的判断里面是A-Z,没有数字判断的


4. 关于cin
见下面一段代码
int golf[5];
for (int i = 0; i < 5 ; i++)
{
cout < < "round # " < <(i+1) < < ": ";
while (!(cin> > golf[i]))
{
cin.clear (); // 重直input
while (cin.get ()!= '\n ')
continue; //清除错误的input
cout < < "Please enter a number "
}
}


重置input是为了防止输入流将表示确定的回车键也当成了一个输入
[解决办法]
1. 不管是向前越界还是向后越界,道理都是一样的,指针指向了非数组以外的位置,它的内容是不定的(至少不是通过数组内部保存的数据就可以预测的)。C++标准不要求做数组越界检查。如arr[5]的越界编译器没有义务指出,大部分的编译器简单地将它转换成*(array+5)。而如 int* pr = arr; pr[5]更是一点语法问题也没有,注意pr已经不是数组了,而是指针。C++一定得支持指针的移位访问,从而支持低层的内存管理。因此有的编译器会对arr[5]越界提出警告(这已经做出超出义务的事了,应该感谢它),但是一定不会拒绝pr[5].
至于int* pr = arr; pr[-2]恰好等于3,这也是很正常的。因为arr是在栈中,栈中的数据是与你的程序密切相关的。如果是地址向上生长的栈,pr[-2]是你在arr之前定义的局部变量(如果你定义过的话),或者是函数的返回地址,活动记录,C++函数调用头等等(具体是什么,依据你的编译器和代码上下文而定)。而如果是地址向下生长的栈,也可能你的程序曾经用到了pr[-2],并赋给了它确定的值,因为一个线程的任何地方,使用的都是同一个栈空间(至于向上生长还是向下生长,是由操作系统决定的)。所以只要你的程序不变,可能你运行一万次,你从pr[-2]中得到的都是同一个值。而修改这个值则是危险的。因为如果不幸修改了函数的返回地址,或者活动记录中的记录链表指针等等,就会造成程序崩溃;如果修改了其他局部变量,也会造成程序运行错误;只有在向下生长的栈中,修改的是目前已经不用的栈空间,则不会有问题(前提是你的修改发生在栈生长到这个位置之前)。因为,越界的数值不定、操作结果未知,是建立在无须知道底层运行机制的基础上。而这个机制往往是存在的。因此,当你发现数值总是同一个时,请不要感到奇怪。

2. 既然是4字节的整型变量,当然占用4字节的地址空间。所以101,102,103都是100的整型变量的一部分。如果你以一个char指向101,并将它改变,你会发现100所在的整型变量变了。
如:
int arr [5] = {0,1,2,3,4};
char* c = (char*)&(arr[0]);
*(c+1) = 1; // c+1为101
此时arr[0]已发生改变。至于是什么值,则于操作系统的字节序有关。在Windows中,是低字节在前,所以此时arr[0] == 256;在其他一些系统中,往往高字节在前,此时arr[0]=65536

3. switch中的default不是必要的。不少人往往增加仅带一个break;的default段。这是一种编程习惯,这里不讨论它的好坏。但是从语法上来说,它确实不是必要的。

4. while段是在cin返回0时才运行的,即此时cin已经出错了。正如jixingzhong所说,错误标志被设置并保留。这时因为一旦发生了一个错误,不管错误原因时什么,如果不做处理,有可能下面的都是错误的。所以cin不会自己清除错误标志,而是将权利交给程序员。而cin.clear();正是告诉cin,“我会处理这个错误的,请继续吧”。如此cin就可以放心地继续下去了。

热点排行