C语言常见面试问题 |
您所在的位置:网站首页 › c语言复试考什么 › C语言常见面试问题 |
说一下 static 关键字的作用 static用于修改变量或函数的链接属性,从外部链接属性变为内部链接属性,变量或函数只能在当前文件访问。对于代码块内部的变量声明,static用于改变变量的存储属性,由自动变量改为静态变量,这个变量会一直保存到程序运行结束。作用域和链接属性不变。对于被 static 修饰的类成员变量和成员函数,它们是属于类的,而不是某个对象,所有对象共享一个静态成员。静态成员通过::来使用说一下const作用 const修饰的变量变常量,只读,不可改变。const修饰指针所指向的变量,常量指针,指针指向内容不可变,如const int* p const修饰指针本身,指针常量,指针本身不可变,int* const pconst修饰函数参数,传递过来的参数在函数内不可以改变。 修饰变量,说明该变量不可以被改变;修饰指针,分为指向常量的指针和指针常量;常量引用,经常用于形参类型,即避免了拷贝,又避免了函数对值的修改;修饰成员函数,说明该成员函数内不能修改成员变量。请说一下 C/C++ 中指针和引用的区别 指针是指向另一个内存的变量,其内容是所指内存的地址,指针有一块自己的内存;引用为存在的对象所起的另外一个名字,即别名。char a;char &ra=a;指针可以为空,指向的内容也可以改变;引用一开始必须初始化,且不能再引用其他对象,从一而终。引用使用是不需要解引用(*),指针需要解引用。sizeof指针是指针本身大小4,sizeof引用是被引用对象的大小指针和引用的自增意义不同,指针++是地址增加,指向下一个内存,引用++是实际值增加。作为函数参数传递时,指针其实是值传递,传地址。指针需要被解引用才可以对对象进行操作,而直接对引用的修改都会改变引用所指向的对象。如果返回动态内存分配的对象或者内存,必须使用指针,引用可能引起内存泄露。请回答一下数组和指针的区别 指针指针是指向另一个内存的变量,其内容是所指内存的地址,指针有一块自己的内存 保存数据的地址,需要*间接访问数据 2.数组 保存数据,通过索引直接访问数据,通常用于固定数目且数据类型相同的元素。数组名是指针常量,是指向数组第一个元素的地址。 注:指针指向一个数组时,可用下标访问和解引用访问,此时指针和数组名作用差不多。 请回答下指针数组和数组指针的区别 指针数组,是指一个数组里面装着指针,也即指针数组是一个数组。如int *a[10],一个有10个指针的数组,每个指针指向一个整形数。 2. 数组指针,是指一个指向数组的指针,它其实还是指针,只不过它指向整个数组。 如int (*p)[10],一个指向有10个元素整型数组的指针。注:[]优先级高于*。 应用: 1、多个字符串一般可存储在二维数组或指针数组中,所以指针数组用于存放多个字符串,或作为函数参数传递多个字符串; 注:a、二级指针和指针数组某些时候是一个意思。 b、指针数组(也就是元素为指针类型的数组)常常作为二维数组的一种便捷替代方式。 一般情况下,这种数组中的指针会指向动态分配的内存区域。 2、数组指针一般用于指向一个二维数组(其类型是一个指向一维数组的指针)来访问数组的元素。 请回答下指针函数和函数指针的区别 指针函数,其本质是一个函数,不过它的返回值是一个指针,如:int *fun(int,int)函数指针,其本质是一个指针,该指针指向了一个函数,所以它是指向函数的指针。如:int (*p)(int, int) p=func, 初始化时给函数名,函数名是该函数的入口地址。 回调函数,就是一个将函数指针作为参数来实现调用其它函数的函数。如:void function( int a, int (*p)(int , int) ) 请你回答一下野指针是什么? 野指针指向了一块随机内存空间,不受程序控制。如1、未初始化的指针,指针指向一个已删除的对象或者指向一块没有访问权限的内存空间;2、free(p)后,p没有置null,。注:指针释放需置NULL。 说一下 C++和 C 的区别 设计思想上:C++是面向对象的语言,而 C 是面向过程的结构化编程语言语法上:C++具有重载、继承和多态三种特性;C++相比 C,增加多许多类型安全的功能,比如强制类型转换;C++支持范式编程,比如模板类、函数模板等说一下#include"stdio.h"和#include区别 #include指系统从系统目录开始搜索stdio.h这个文件。#include“stdio.h”指系统先在当前目录(源文件所在目录)搜索stdio.h这个文件,若没找到,再到系统目录寻找。请你说一说 strcpy 和和 strlen strcpy 是字符串拷贝函数,原型:char *strcpy(char* dest, const char *src);从 src 逐字节拷贝到 dest,直到遇到'\0'结束,因为没有指定长度,可能会导致拷贝越界,造成缓冲区溢出漏洞,安全版本是 strncpy 函数。strlen 函数是计算字符串长度的函数,返回从开始到'\0'之间的字符个数。请你来说一下堆和栈的区别 1)申请方式: 栈由系统自动分配和管理,堆由程序员手动分配和管理。 2)效率: 栈由系统分配,速度快,不会有内存碎片。 堆由程序员分配,速度较慢,可能由于操作不当产生内存碎片。 3)扩展方向 栈从高地址向低地址进行扩展,堆由低地址向高地址进行扩展。 4)程序局部变量是使用的栈空间,new/malloc 动态申请的内存是堆空间,函数调用时会进行形参和返回值的压栈出栈,也是用的栈空间 请你来说一说重载、覆盖和重写 重载:函数名相同,但是参数参数不同(个数,类型),返回值类型没有要求,在同一作用域中覆盖:是指派生类中存在重新定义基类的函数,其函数名,参数列表、返回值类型必须同父类中的相对应被覆盖的函数严格一致重写:子类继承了父类,父类中的函数是虚函数,在子类中重新定义了这个虚函数,这种情况是重写请你说一说你理解的多态和虚函数 多态的实现主要分为静态多态和动态多态,静态多态主要是重载,在编译的时候就已经确定; 动态多态是用虚函数机制实现的,在运行期间动态绑定。举个例子:一个父类类型的指针指向一个子类对象时候,使用父类的指针去调用子类中重写了的父类中的虚函数的时候,会调用子类重写过后的函数,在父类中声明为加了 virtual 关键字的函数,在子类中重写时候不需要加 virtual也是虚函数。 2.虚函数:指向基类的指针在操作它的多态类对象时,会根据不同的类对象调用相应对象的函数。 虚函数的实现:在有虚函数的类中,类的最开始部分是一个虚函数表的指针,这个指针指向一个虚函数表,表中放了虚函数的地址,实际的虚函数在代码段(.text)中。当子类继承了父类的时候也会继承其虚函数表,当子类重写父类中虚函数时候,会将其继承到的虚函数表中的地址替换为重新写的函数地址。使用了虚函数,会增加访问内存开销,降低效率。 请你来说一说 extern “C” C++调用 C 函数需要 extern C,因为 C 语言没有函数重载 请你回答一下 new/delete 与与 malloc/free 的区别是什么 首先,new/delete 是 C++的关键字,而 malloc/free 是 C 语言的库函数(stdlib),后者使用必须指明申请内存空间的大小,对于类类型的对象,后者不会调用构造函数和析构函数malloc 需要给定申请内存的大小,返回的指针需要强转。new 会调用构造函数,不用指定内存大小,返回的指针不用强转。int main( int argc, char** argv )参数意义 第一个argc,是记录你输入在命令行上的参数(字符串)个数;第二个argv[]是个指向字符串的指针数组,即数组元素是指向输入在命令行上的每个参数(字符串)的指针。argv[0]:存储程序名; argv[1]:指向在DOS命令行中执行程序名后的第一个字符串; argv[2]:指向第二个字符串。 结构体数据对齐原则如下: 整体空间是占用空间最大成员所占字节数的整数倍;按成员顺序给每个成员分配内存;成员前面已摆放的空间大小必须是该成员类型大小的整数倍,如果不够则补齐。char 1 字节; short 2 字节; int 4 字节; float 4 字节; long 4 字节; double 8 字节; long long 8 字节;
源代码-------------预处理、编译、汇编、链接-----------可执行文件 .h头文件中的ifndef/define/endif 的作用? 答:防止该头文件被重复引用。 说一下volatile关键字作用 编译优化时,为提高存取速度,有时会把变量读取到寄存器,方便读取;但有时别的线程改变了变量的值,但寄存器值不变,造成程序读取值不一致,所以使用volatile从变量内存中读取。 修饰某个变量,表明某个变量的值可能随时被外部改变,因此对这些变量的存取不能缓存到寄存器,每次使用时需要重新读取,从变量的地址中(内存中)读取数据。 场景:多用于多线程或多CPU编程 说一下C语言中的内存分区 代码区:存放CPU执行的机器指令,二进制代码。全局存储区:存放全局变量和静态变量。分为未初始化全局变量和静态变量数据区bss段和已初始化全局变量和静态变量数据区data段;文本常量区:字符串常量存在在这里,程序结束后系统释放;堆区heap:由程序员手动分配释放,由malloc和free分配和释放。程序员不释放,程序结束系统释放。栈区stack:由编译器自动分配和释放,存放函数的参数值(形参)、局部变量的值等。什么是预编译/预处理,何时需要预编译? 答:预编译又称为预处理,是做些代码文本的替换工作。处理#开头的指令,比如拷贝#include包含的文件代码,#define宏定义的替换,条件编译等,就是为编译做的预备工作的阶段,主要处理#开始的预编译指令,预编译指令指示了在程序正式编译前就由编译器进行的操作,可以放在程序中的任何位置。 c编译系统在对程序进行通常的编译之前,先进行预处理。c提供的预处理功能主要有以下三种:1)宏定义 2)文件包含 3)条件编译 总是使用不经常改动的大型代码体。2、程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种情况下,可以将所有包含文件预编译为一个预编译头。 C语言实现程序跳转到绝对地址0x100000处执行 强制把绝对地址0x100000转换成函数指针(void (*)())0x100000,然后再调用它: ((void(*)()) 0x100000)() 写一个“标准”宏(对于一个频繁使用的短小函数) 输入两个参数,输出较小的一个:#define MIN(A,B) ( ( (A) < (B))? (A) : (B)) 定义一个宏,比较a、b的大小,不要用大于、小于和IF运算符:#define MAX(A,B) (((A)-(B))>>31 ? (B) : (A)) 定义一个宏将变量的第n位置1:#define SET(a,n) ( a | ( 1 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |