打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
C语言学习趣事_经典面试题系列

 上次说了一些有意思的面试题, 今天我们结着看看一些关于指针和sizeof的面试题:

下面是我看到的一些面试题

1、简述   

char * const p;
        char const *p;
        const  char *p;

  之间的区别。

   首先讨论:
              char  * const p;   这里可以知道const修饰是指针变量p; 因此指针p的指向不能改变,这样的变量定义必须首先初始化,否则将不能编译通过。但是p指向的变量的存储内容可以改变。

Exp:

     char chTest1;
                      char chTest2;
                      char  * const p=&chTest1;
                      // p=&chTest2;   这个地方是错误的,不能这样赋值
*p=‘c’;
chTest1=‘b’;

   接下来讨论:
              char const *p;     这里可以知道const修饰的是*p; 因此可以知道不能通过*p指向来改变变量的值; 但是指针p的指向可以改变,而且可以通过原变量进行改变值。
            

Exp:

                    char chTest1;
                    char chTest2;
                    char const *p=&chTest1;
p=&chTest2;
chTest=‘a’;

这里可以知道: 

1)p的指向可以改变
2)不能通过*p= 某个值进行赋值
3)指针指向的变量的值自己可以改变。
    
最后讨论:

const char  *p=&chTest1; 

这里可以知道const修饰的是*p;

因此这个与char const *p;

具有相同的效果。


Exp:

char chTest1;
               char chTest2;
               const char  *p=&chTest1;
               p=&chTest2;
               chTest1='a';
              // *p='a'; 这个地方错误, 不能这样修改值。

   总结:
         修饰符仅对其修饰的对象起作用,对别的变量不起作用。

6、以下代码中的两个sizeof用法有问题吗?

  void UpperCase( char str[] ) // 将 str 中的小写字母转换成大写字母 
           {    
                for( size_t i=0; i <sizeof(str)/sizeof(str[0]); ++i )       
                   if( 'a' <=str[i] && str[i] <='z' )            
                             str[i] -= ('a'-'A' ); 
             } 
            char str[] = 'aBcDe'; 
            cout < < 'str字符长度为: ' < < sizeof(str)/sizeof(str[0]) < < endl; 
            UpperCase( str ); 
            cout < < str < < endl; 

  Exp:
     这个问题的考察点是sizeof的用法。那么我们应该如何看待这个问题呢?


1、这里首先我们需要知道的是sizeof 是个运算符, 它具有运算的优先级别, 那么sizeof运算的优先级在什么地方呢?


可以查看运算符优先级的定义: sizeof 的优先级和 *p(P为指针)、&p(变量,取地址)的优先级一样, 排在优先级的第二位。


2、其次要明白sizeof关键字的作用

sizeof 关键字返回的是操作数在内存中占用的字节数。

这里要看sizeof操作符的操作对象:


1) 类型关键字

sizeof(int):  这个取决系统的定义, 当在32位机器上时; sizeof int == 4
                            而在16位机器上时, sizeof int == 2
2) 变量

          int iTest;
          sizeof iTest;  这样返回的是这种变量类型在内存中所占用的空间。
          即:sizeof iTest == sizeof int;


3) 字符串字面值


           sizeof 'abcd';
          那么返回的是:字符串在内存空进中占用的字节数。 这里我们知道'abcd'在内存中占用的是5个字节,那么很显然有sizeof 'abcd'==5;


4) 数组
         这里有点难度
         char chTest[5];
        sizeof(chTest)==5; //这里可以知道chTest数组有5个元素,并且每个元素占用一个字节,因此sizeof(chTest)==5;

        那么如果我们这样定义呢?
         int iTest[5];
        sizeof(iTest)= ?  // 答案是20 , 因为有5个元素,每个元素占4个字节,所以占用20个字节的空间。
      
        二维数组呢?
         char chTest[10][20];
         sizeof(chTest)= ?  //200
        既然sizeof(chTest)==200; 那么sizeof(chTest[10])= ?  答案是 20 .
        
        又如:
         int iTest[10][20];
         sizeof(iTest)= ?  // 800
         同样 sizeof(iTest[10])= ?  答案是 80 

       通过这里我们得出结论:
       对于sizeof操作数组的时候要分两种情况:
a、 一维数组
           sizeof(数组名) 返回的是 数组元素个数 * 每个元素占用的字节数
          sizeof(数组名[n]) 返回的是:数组类型定义的单个变量所占用的字节数
         即:
              int iTest[4];
          则
              sizeof(iTest)=14;
              sizeof[iTest[1]]=4;  
             
b、 多维数组
          sizeof(数组名)     返回的是:一维的长度*二维的长度*....* 每个元素占用的字节数
          sizeof(数组名[n])  返回的是:其后面各位长度的乘积* 每个元素占用的字节数,
                              这样必须保证sizeof的操作数没有取到最后一维。
          即:int iTest[2][3][4];
                sizeof(iTest[2][3])= 4*sizeof[int]=16; 
c) 多维数组
         sizeof(数组变量定义式);
         即:
          int iTest[2][3][4][5];
          sizeof(iTest[2][3][4][5])= ?  
         这里返回的是 数组的维数 就是 4 。
        
5、传递的是指针的时候
         如果操作的是指针那么情形又如何呢?
         这里也分两种情形:


1)当操作数是指针本身的时候
         Exp:
            int *iTest;
          那么
            sizeof(iTest) = ? //这里有一个规则,当sizeof操作变量的时候,返回的是变量本身的存储长度, 因此
                                 //如果在16位的系统中, 这里返回2; 而在32位系统中返回的是4;
                      
2)当操作数有* 取值间接运算符号时
         Exp:
            int *iTest;
          那么
            sizeof(*iTest) = ? // 这里返回的是 4, 其实返回的是sizeof(int)的长度; 即返回的是其指向的
                                  //变量类型的 所占用的空间
        可以用:
            float *fTest;
           sizeof(*fTest)= ?  // 这里返回的值是 4
           sizeof(fTest)= ?     //  取决于系统  16位的系统返回 2, 32位系统返回 4, 64位系统返回8 即地址总线的宽度。

      现在回到我们的问题:

 void UpperCase( char str[] ) // 将 str 中的小写字母转换成大写字母 
           {    
                for( size_t i=0; i <sizeof(str)/sizeof(str[0]); ++i )       
                   if( 'a' <=str[i] && str[i] <='z' )            
                             str[i] -= ('a'-'A' ); 
             } 
            char str[] = 'aBcDe'; 
            cout < < 'str字符长度为: ' < < sizeof(str)/sizeof(str[0]) < < endl; 
            UpperCase( str ); 
            cout < < str < < endl;   

1、首先确定sizeof的语法问题:

 for( size_t i=0; i <sizeof(str)/sizeof(str[0]); ++i )    //语法没有问题           
            sizeof(str)/sizeof(str[0])    //语法也没有问题

2、接着确定逻辑有没有问题
           我们先看: sizeof(str[0])分析可知str[0]是个char的变量 , 因此占用一个字节;
           再看:
                sizeof(str);
           数组当做实参传递的时候,相当于传的指针,在函数里面sizeof就是取指针所占的内存空间所以是4个字节,这样是求不出整个数组的大小的!


3、 既然不能这样求那么我们运行的时候怎样才可以得到正确结果呢

使用strlen就可以

          这个可以在VC6.0中用下列代码测试:
        Exp:

/*
 * test the sizeof key word
 *
 */
#include <stdio.h>
#include <conio.h>

#include <string.h>

 void UpperCase( char str[] )  
{   int i;
    printf('sizeof :%d,%d',sizeof(str),sizeof(str[0]));

   printf('strlen :%d',strlen(str));

    for(i=0; i< strlen(str)-1 ;++i )
        if( 'a' <=str[i] && str[i] <='z' )
               str[i] -= ('a'-'A' );
}
int main(int argc,char *argv[])
{
    char  chTest[]='abcd';
    printf('%d\n',sizeof(chTest));
    UpperCase(chTest);

   puts(chTest);// 因为我们知道chTest[4]='\0'. 所以虽然没有传递,但是还是可以实现转换的功能
    getch();
}

   通过这个例子可以看出来, 有些时候确实不是我们想的那样,


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
C语言面试题
C 知识点
c++知识 - 洋男的日志 - 网易博客
预处理、const、static与sizeof
c++指针经典应用,多年学习笔记,不看后悔
100个开源C/C++项目中的bugs
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服