• 面试题——超


    1    int (*a[10]) (int)

    注意指针数组和数组指针的区别:
    int(*a[10])(int):a是这样一个数组,它有十个元素,每个元素都是一个函数指针,所指向的函数是带一个int参数返回值也是int。
    int(*a)[10](int):a是一个函数指针,它所指向的函数是带一个int参数,返回值是一个有10个int元素的数组。

     

    2    int * (* (*fp1) (int) ) [10]; 右左法则
    阅读步骤: 
    1. 从变量名开始 -------------------------------------------- fp1 
    2. 往右看,什么也没有,碰到了),因此往左看,碰到一个* ------ 一个指针 
    3. 跳出括号,碰到了(int) ----------------------------------- 一个带一个int参数的函数 
    4. 向左看,发现一个* --------------------------------------- (函数)返回一个指针 
    5. 跳出括号,向右看,碰到[10] ------------------------------ 一个10元素的数组 
    6. 向左看,发现一个* --------------------------------------- 指针 
    7. 向左看,发现int ----------------------------------------- int类型 
    总结:fp1被声明成为一个函数的指针,该函数返回指向指针数组的指针。

    http://bbs.csdn.net/topics/380142634引用链接内容

    右左法则:首先从最里面的圆括号看起,然后往右看,再往左看。每当遇到圆括号时,就应该掉转阅读方向。一旦解析完圆括号里面所有的东西,就跳出圆括号。重复这个过程直到整个声明解析完毕。 
                      笔者要对这个法则进行一个小小的修正,应该是从未定义的标识符开始阅读,而不是从括号读起,之所以是未定义的标识符,是因为一个声明里面可能有多个标识符,但未定义的标识符只会有一个。 
    现在通过一些例子来讨论右左法则的应用,先从最简单的开始,逐步加深: 
    int   (*func)(int   *p); 
    首先找到那个未定义的标识符,就是func,它的外面有一对圆括号,而且左边是一个*号,这说明func是一个指针,然后跳出这个圆括号,先看右边,也是一个圆括号,这说明(*func)是一个函数,而func是一个指向这类函数的指针,就是一个函数指针,这类函数具有int*类型的形参,返回值类型是int。 
    int   (*func)(int   *p,   int   (*f)(int*)); 
    func被一对括号包含,且左边有一个*号,说明func是一个指针,跳出括号,右边也有个括号,那么func是一个指向函数的指针,这类函数具有int* 和int(*)(int*) 这样的形参,返回值为int类型。

    再来看一看func的形参int(*f)(int*) ,类似前面的解释,f也是一个函数指针,指向的函数具有int*类型的形参,返回值为int。 
    int   (*func[5])(int   *p); 
    func右边是一个[]运算符,说明func是一个具有5个元素的数组,func的左边有一个*,说明func的元素是指针,要注意这里的*不是修饰func的,而是修饰func[5]的,原因是[]运算符优先级比*高,func先跟[]结合,因此*修饰的是func[5]。跳出这个括号,看右边,也是一对圆括号,说明func数组的元素是函数类型的指针,它所指向的函数具有int*类型的形参,返回值类型为int。 
    int   (*(*func)[5])(int   *p); 
    func被一个圆括号包含,左边又有一个*,那么func是一个指针,跳出括号,右边是一个[]运算符号,说明func是一个指向数组的指针,现在往左看,左边有一个*号,说明这个数组的元素是指针,再跳出括号,右边又有一个括号,说明这个数组的元素是指向函数的指针。总结一下,就是:func是一个指向数组的指针,这个数组的元素是函数指针,这些指针指向具有int*形参,返回值为int类型的函数。 
    int   (*(*func)(int   *p))[5]; 
    func是一个函数指针,这类函数具有int*类型的形参,返回值是指向数组的指针,所指向的数组的元素是具有5个int元素的数组。 
    要注意有些复杂指针声明是非法的,例如: 
    int   func(void)   [5]; 
    func是一个返回值为具有5个int元素的数组的函数。但C语言的函数返回值不能为数组,这是因为如果允许函数返回值为数组,那么接收这个数组的内容的东西,也必须是一个数组,但C语言的数组名是一个右值,它不能作为左值来接收另一个数组,因此函数返回值不能为数组。 
    int   func[5](void); 
    func是一个具有5个元素的数组,这个数组的元素都是函数。这也是非法的,因为数组的元素除了类型必须一样外,每个元素所占用的内存空间也必须相同,显然函数是无法达到这个要求的,即使函数的类型一样,但函数所占用的空间通常是不相同的。 
    作为练习,下面列几个复杂指针声明给读者自己来解析,答案放在第十章里。 
    int   (*(*func)[5][6])[7][8]; 
    int   (*(*(*func)(int   *))[5])(int   *); 
    int   (*(*func[7][8][9])(int*))[5]; 
    实际当中,需要声明一个复杂指针时,如果把整个声明写成上面所示的形式,对程序可读性是一大损害。应该用typedef来对声明逐层分解,增强可读性,例如对于声明: 
    int   (*(*func)(int   *p))[5]; 
    可以这样分解: 
    typedef     int   (*PARA)[5]; 
    typedef   PARA   (*func)(int   *); 

     

    3    int a=100,c=1;int &b=a;b=c;  a,b?

     int &b=a,b是a的引用,a、b等价,同一玩意儿,故而,a=b=1 。引用一次初始化,不可更换引用的对象,可以改变所引用的对象的值。

     

    4    float x;x与0比较

    x-0<0.000001; 0-x<0.000001 。

     

    5    union A{long l; char c[5];char s;} ;

        struct B{int i;A a;doublie d;}b ;求sizeof(b)+sizeof(a)的值。

      对齐 8+(4+8+8)=28

     

    6    虚函数 ?作用 ?什么函数不可声明为虚函数?

      定义:虚函数必须是基类的非静态成员函数,其访问权限可以是protected或public;没有继承特性的函数不能为虚函数

    在基类的类定义中定义虚函数的一般形式:virtual 函数返回值类型 虚函数名(形参表)  { 函数体 }

      作用:

    虚函数的作用是实现动态联编——多态,也就是在程序的运行阶段动态地选择合适的成员函数,在定义了虚函数后,可以在基类的派生类中对虚函数重新定义,在派生类中重新定义的函数应与虚函数具有相同的形参个数和形参类型,以实现统一的接口,不同定义过程。如果在派生类中没有对虚函数重新定义,则它继承其基类的虚函数。

    当程序发现虚函数名前的关键字virtual后,会自动将其作为动态联编处理,即在程序运行时动态地选择合适的成员函数。

      使用方法:

    动态联编规定,只能通过指向基类的指针或基类对象的引用来调用虚函数;

    其格式: 指向基类的指针变量名->虚函数名(实参表)    或      基类对象的引用名. 虚函数名(实参表)

      其它说明:  

    虚函数是C++多态的一种表现:例如:子类继承了父类的一个函数(方法),而我们把父类的指针指向子类,则必须把父类的该函数(方法)设为virtual(虚函数)。  

    使用虚函数,我们可以灵活的进行动态绑定,当然是以一定的开销为代价。 如果父类的函数(方法)根本没有必要或者无法实现,完全要依赖子类去实现的话,可以把此函数(方法)设为virtual 函数名=0

    我们把这样的函数(方法)称为纯虚函数。如果一个类包含了纯虚函数,称此类为抽象类 。

      什么函数不可声明为虚函数?答案: static 友元 构造 

    一个类中将所有的成员函数都尽可能地设置为虚函数总是有益的。 
    设置虚函数须注意: http://blog.csdn.net/reille/article/details/6214165
    1:只有类的成员函数才能说明为虚函数; 
    2:静态成员函数不能是虚函数; 只拷贝一份,所有代码共享;
    3:内联函数不能为虚函数; 编译时进行代码替换,而虚函数是在运行时实现的;
    4:构造函数不能是虚函数; 为了初始化对象变量的,只有在生成一个对象之后才能发挥多态作用,而虚函数是在运行时才起作用;

    5:普通函数不能是虚函数;(非成员函数);

    6:友元函数不能是虚函数;不是类的成员函数,不能被继承
    7:析构函数可以是虚函数,而且通常声明为虚函数。

    要想成为虚函数,必须能够被取到地址.内联函数不能被取到地址所以不能成为虚函数;inline  virtual  void  f(),不能保证函数f()一定是内联的,只能保证f()是虚函数;

    你不能够确定一个函数到底是不是inline的.inlien关键字只是对编译器的一个建议:"如果有可能,请把此函数搞成inline的"。

     

    7  static 全局 局部 函数与普通函数区别

     static全局变量与普通全局变量区别:static只初始化一次,防止在其他文件单元中被引用。

     static局部变量与普通局部变量区别:static只被初始化一次,下一次依据上一次结果值。

    static函数与普通函数区别:static函数在内存中只有一份,而普通函数在每个被调用中维持一份复制品。

     

    8  存储过程? 作用 优点

    事务:在数据库系统上执行并发操作时事务是做为最小的控制单元来使用的;;开始事物:BEGIN TRANSACTION;;提交事物:COMMIT TRANSACTION;;回滚事务:ROLLBACK TRANSACTION

         ①原子性(Atomicity):事务中的所有元素作为一个整体提交或回滚,是不可折分的,事务是一个完整的操作。
         ②一致性(Consistemcy):事物完成时,数据必须是一致的,也就是说,和事物开始之前,数据存储中的数据处于一致状态。保证数据的无损。
         ③隔离性(Isolation):对数据进行修改的多个事务是彼此隔离的。这表明事务必须是独立的,不应该以任何方式来影响其他事务。
         ④持久性(Durability):事务完成之后,它对于系统的影响是永久的,该修改即使出现系统故障也将一直保留,真实的修改了数据库

    存储过程:一组为了完成特定功能的SQL 语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象,任何一个设计良好的数据库应用程序都应该用到存储过程。就本质而言,触发器也是一种存储过程。存储过程在运算时生成执行方式,所以,以后对其再运行时其执行速度很快。
    ①重复使用。存储过程可以重复使用,从而可以减少数据库开发人员的工作量。
    ②提高性能。存储过程在创建的时候在进行了编译,将来使用的时候不再重新翻译。一般的SQL语句每执行一次就需要编译一次,所以使用存储过程提高了效率。
    ③减少网络流量。存储过程位于服务器上,调用的时候只需要传递存储过程的名称以及参数就可以了,因此降低了网络传输的数据量。
    ④安全性。参数化的存储过程可以防止SQL注入式攻击,而且可以将Grant、Deny以及Revoke权限应用于存储过程。
    简单讲:
    1.存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般SQL语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。
    2.当对数据库进行复杂操作时(如对多个表进行Update,Insert,Query,Delete时),可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。
    3.存储过程可以重复使用,可减少数据库开发人员的工作量
    4.安全性高,可设定只有某些用户才具有对指定存储过程的使用权
    表述为:
    (1) 能实现模块化程序设计。存储过程是根据实际功能的需要创建的一个程序模块,并被存储在数据库中。以后用户要完成该功能,只要在程序中直接调用该存储过程即可,而无需再编写重复的程序代码。存储过程可由数据库编程方面的专门人员创建,并可独立于程序源代码而进行修改和扩展。
    (2) 使用存储过程可以提高执行效率。当客户程序需要访问服务器上的数据时,一般要经过5个步骤:
     ● 查询语句被发送到服务器;
     ● 服务器编译T-SQL语句;
     ● 优化产生查询执行计划;
     ● 数据库引擎执行查询;
     ● 执行结果发回客户程序。
    如果执行存储在客户端本地的T-SQL程序,那么每次执行该程序时,对于程序中的每一条语句都要经过以上5个步骤。而存储过程在创建时就被编译和优化,当存储过程第一次被执行时,SQL Server为其产生查询计划并将其保存在内存中,这样以后在调用该存储过程时就不必再进行编译,即以上5个步骤中的第2步和第3步就被省略了,这能大大改善系统的性能。 
    (3) 减少网络流量。一个需要数百行T-SQL代码的操作,如果将其创建成存储过程,那么使用一条调用存储过程的语句就可完成该操作。这样就可避免在网络上发送数百行代码,从而减少了网络负荷。
    (4) 可作为安全机制使用。管理员可以不授予用户访问存储过程中涉及的表的权限,而只授予执行存储过程的权限。这样,既可以保证用户通过存储过程操纵数据库中的数据,又可以保证用户不能直接访问存储过程中涉及的表。用户通过存储过程来访问表,所能进行的操作是有限制的,从而保证了表中数据的安全性。
    缺点:
    1:调试麻烦,但是用 PL/SQL Developer 调试很方便!弥补这个缺点。
    2:移植问题,数据库端代码当然是与数据库相关的。但是如果是做工程型项目,基本不存在移植问题。
    3:重新编译问题,因为后端代码是运行前编译的,如果带有引用关系的对象发生改变时,受影响的存储过程、包将需要重新编译(不过也可以设置成运行时刻自动编译)。
    4: 如果在一个程序系统中大量的使用存储过程,到程序交付使用的时候随着用户需求的增加会导致数据结构的变化,接着就是系统的相关问题了,最后如果用户想维护该系统可以说是很难很难、而且代价是空前的,维护起来更麻烦。

    构建有参存储过程 CREATE PROCEDURE au_info
       @lastname varchar(40),@firstname varchar(20)
    AS
    SELECT au_lname, au_fname, title, pub_name FROM authors a INNER JOIN titleauthor ta ON a.au_id = ta.au_id 
       WHERE  au_fname = @firstname AND au_lname = @lastname
    GO   

    执行    EXECUTE au_info @lastname = 'Dull', @firstname = 'Ann'

     

    9  模态对话框 非模态对话框

    二者的区别在于当对话框打开时,是否允许用户进行其他对象的操作。
    模态对话框垄断了用户的输入。当一个模态对话框打开时,用户只能与该对话框进行交互,而其他用户界面对象收不到输入信息。模态对话框下,用户需要操作目标对话框就必须先操作模态对话框。
    非模态对话框(Nonmodal Dialogue Box,又叫做无模式对话框),与模态对话框不同,当用户打开非模态对话框时,依然可以操作其他窗口。    #include "Dialogproty.h"
     

    10  编程 判断链表是否有环

     

    11  编程 给定16位二进制数 eg:1101 0101 1011 0111

    运算规则:1101+101+1011+111=2324输出

     

    12  什么是COM线程模型

    COM即为组件对象模型,他定义一种二进制标准,使得任何编程语言存取它所编写的模块

     

    http://blog.csdn.net/jokes000/article/details/7070520

    http://www.cnblogs.com/henryhu/archive/2010/02/20/1669939.html

    http://hi.baidu.com/geogrex/item/a982ba0f76273cf7f45ba681

    http://blog.csdn.net/lock0812/article/details/2644109

    http://www.nowamagic.net/librarys/veda/detail/2245

    http://blog.csdn.net/thefutureisour/article/details/8174313

    http://blog.sina.com.cn/s/blog_725dd1010100tqwp.html

     

  • 相关阅读:
    lucene初探
    直接插入排序算法(java)
    快速排序优化算法
    大根堆
    学习资料地址
    Lucene:基于Java的全文检索引擎简介
    开关按钮
    微信小程序—如何获取用户输入文本框的值
    微信小程序—获取用户网络状态和设备的信息
    Bootstrap 导航栏
  • 原文地址:https://www.cnblogs.com/qq1129496211/p/4061883.html
Copyright © 2020-2023  润新知