c语言免面试题,写一个"标准"宏min,C++一些常见面试题---持续更新

1.变量的声明何定义有什么区别

变量的定义为变量分配地址和存储空间,变量的声明不分配地址。一个变量可以在多个地方声明,但是只在一个地方定义。同时加入extern修饰的变量的声明,说明此变量将在文件以外或在文件后面部分定义。

说明-很多时候一个变量,只是声明不分配内存空间,直到具体使用时才初始化,分配内存空间,如外部变量。

int main()

{

extern int A;

//这是个声明而不是定义,声明A是一个已经定义了的外部变量

//注意:声明外部变量时可以把变量类型去掉如:extern A;

dosth(); //执行函数

}

int A; //是定义,定义了A为整型的外部变量

2.简述#ifdef、#else、#endif和ifndef的作用

在程序中可以利用#ifdef、#endif将某一个模块的代码特殊定义,以向特定用户提供该功能。在不需要用户可以将其屏蔽。

#ifdef MATH

#include "math.c"

#endif

同时在window下应对硬件编译的时候,可以利用这种编译绕过硬件,直接进行编译得出预期的结果。

注意-虽然不用条件编译命令而直接用if语句也能达到要求,但那样做目标程序长,运行时间长,进行条件编译时,可以减少被编译的语句,从而减少目标程序的长度,减少运行时间。

3.写出int、bool、float、指针变量与"零值"比较的if语句

//int与零值比较

if ( n == 0 )

if ( n != 0 )

//bool与零值比较

if (flag) // 表示flag为真

if (!flag) // 表示flag为假

//float与零值比较

const float EPSINON = 0.00001;

if ((x >= - EPSINON) && (x <= EPSINON) //其中EPSINON是允许的误差(即精度)。

//指针变量与零值比较

if (p == NULL)

if (p != NULL)

4.结构体可以直接赋值吗

声明时可以直接初始化,同一结构体的不同对象之间也可以直接赋值,但是当结构体中含有指针"成员"时一定要小心。

注意-当有多个指针指向同一段内存时,某个指针释放这段内存可能会导致其他指针的非法操作。因此在释放前一定要确保其他指针不再使用这段内存空间

5.sizeof与strlen的区别

sizeof是一个操作符,strlen是库函数

sizeof的参数可以是数据的类型,也可以是变量。而strlen只能以结尾'\0'的字符串做参数

编译器在编译时就计算出了sizeof的结果,而strlen函数必须在运行时才能计算出来,并且sizeof计算的数据类型占内存的大小,而strlen计算的是字符串实际的长度

数组做sizeof的参数不退化,传递给strlen就退化为指针了

6.c语言的关键字static和C++的关键字static有什么区别

在c中,static关键字用来修饰局部静态变量和外部静态变量、函数。在C++中除了上述功能外,还用来定义类的成员变量和函数。即静态成员和静态成员函数

注意-在编程时static的记忆性,和全局性的特点可以让在不同时期调用的函数进行通信,传递信息,而C++的静态成员则可以在多个对象实例间进行通信,传递信息

7.c语言的Malloc和C++中new delete的区别

new、delete是操作符,可以进行重载,只能在C++中使用

malloc、free是函数,可以覆盖,c与C++中都可以使用

new可以调用对象的构造函数,相应delete调用的是析构函数

malloc仅仅分配内存,free仅仅回收内存,并不执行构造与析构函数

new、delete返回的是某种数据类型指针,malloc、free返回的是void指针

注意-malloc申请的内存空间要用free释放,而new申请的内存空间要用delete释放,不要混用

8.写一个"标准"宏MIN

# d e f i n e m i n ( a , b ) ( ( a ) < = ( b ) ? ( a ) : ( b ) )

9.++i和i++的区别

++i自增1再返回

i++先返回1,再自增1

10.volatile有什么作用

状态寄存器一类的并行设备硬件寄存器

一个中断服务子程序会访问到的非自动变量

多线程间被几个任务共享的变量

注意-虽然volatile在嵌入式方面应用比较多,但是在PC端软件的多线程中,volatile修饰的临界变量也是非常实用的

11.一个参数可以既是const又是volatile吗

答案是可以的,用const与volatile同时修饰变量,表示这个变量在程序内部是只读的,不能改变的,只在程序外部变化下改变,并且编译器不会优化这个变量。每次使用这个变量时,都要小心地去内存读取这个变量的值,而不是去寄存器读取它的备份。

注意-在此一定要注意const的意思,const只是不允许程序中的代码改变某一变量,其在编译期发挥作用,它并没有实际地禁止某段内存的读写性。

12.a和&a有什么区别?

&a表示的意思时变量a的地址

a在不同的地方有不同的含义

在声明语句中,a只说明a是一个变量,int a

在其他语句中,a前面没有操作数且a是一个指针时,a代表指针a指向的地址内存放的数据,如b=*a

13.用c编译一个死循环程序

while(1)

{ }

注意-很多途径都可以实现同一种功能,但是不同的方法时间和空间占用度不同,特别是读与嵌入式软件,处理器速度比较慢,存储空间较小,所以时间和空间优势时选择各种方法的首要考虑条件。

14.全局变量和局部变量有什么区别?是怎么实现的?操作系统和编译器是怎么知道的?

全部变量是整个程序都可以访问的变量,谁都可以访问,生存期在整个程序从运行到结束-在程序结束时所占内存释放

局部变量存在于模块(子程序,函数)中,只有所在模块可以访问,其他模块不可直接访问,模块结束调用完毕,局部变量消失,所占据的内存释放

操作系统和编译器,可能是通过内存分配的位置来知道的,全局变量分配在全局数据段并且在程序运行得到时候记载,局部变量则分配在堆栈里面。

15.简述C和C++程序编译的内存分配情况

从静态存储区域分配-内存在程序编译时就已经分配好,这块内存在程序的整个运行期间都存在。速度快、不容易出错,因为有系统会善后。例如全局变量,static变量,常量字符串等

在栈上分配-在执行函数时,函数内局部变量的存储单元都在栈上创建,函数执行结束时这些存储单元自动释放。

在堆上分配-即动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在何时使用free和delete释放内存。动态内存的生存期有程序员决定。如果在堆上分配了空间,就有责任回收它,否则运行的程序会出现内存泄漏,频繁地分配和释放不同大小的堆空间将会产生堆内碎块

16.简述strcpy、sprintf和memcpy的区别

可以对四个不同的方面来进行区别

操作对象不同--strcpy的俩哥哥操作对象均为字符串,sprintf的操作源对象可以是多种数据类型,目的操作对象是字符串,memcpy的两个对象就是两个任意可操作的内存地址,并于限于何种数据类型

执行效率不同--memcpy效率最高,strcpy次之,sprintf的效率最低

实现功能不同--strcpy主要实现字符串变量间的拷贝,sprintf主要实现其他数据类型格式到字符串的转化,memcpy主要内存块间的拷贝

17.请解析((void ()( ) )0)( )的含义

void (0)( )-是一个返回值为void,参数为空的函数指针0

(void ()( ))0-把0转变成一个返回值为void,参数为空的函数指针

(void ()( ))0-在上句的基础上加表示整个是一个返回值为void,无参数,并且起始地址为0的函数的名字

((void (*)( ))0)( )-表示为上句的函数名所对应函数的调用

18.C语言的指针和引用和C++有什么区别

指针有自己的一块空间,而引用只是一个别名

使用sizeof看一个指针的大小是4,而引用是被引用对象的大小

作为参数传递时,指着需要被解引用才可以对对象进行操作,而直接引用的修改都会改变引用所指的对象

可以用const指针,但是没有const引用

指针在使用中可以指向其他对象,但是引用只是一个对象的引用,不能被改变

指针可以有多级指针,而引用止于一级

指针和引用使用++运算符的意义不一样

如果返回动态内存分配的对象或者内存,必须使用指针,引用可能引起内存泄漏

19.typedef和define有什么区别

用法不同--typedef用来定义一种数据类型的别名,增强程序的可读性。define主要用来定义常量,以及书写复杂使用频繁的宏

执行时间不同--typedef是编译过程的一部分,有类型检查的功能。define是宏定义,是预编译的部分,其发生在编译之前,只是简单的进行字符串的替换,步进行类型的检查

作用域不同--typedef有作用域限定,define不受作用域约束,只要在define声明后的引用都是正确的

对指针的而操作不同--typedef和define定义的指针时有很大的区别

注意的是--typedef定义的是语句,因为句尾加上分号,而define不是语句千万不能在句尾加上分号

20.指针常量与常量指针的区别

指针常量是指定义了一个指针,这个指针的值只能在定义时初始化,其他地方不能改变。常量指针是指定义一个指针,这个指针指向一个只读的对象,不能通过常量指针来改变这个对象的值。指针常量强调的是指针的不可改变性,而常量指针强调的是指针对其所指对对象的不可改变性

注意-无论是指针常量还是常量指针,其最大的用途就是作为函数的形式参数,保证实参在被调用函数的不可改变特性。

21.简述队列和栈的异同

队列和栈都是线性存储结构,但是两者的插入和删除数据的操作不同,队列是先进先出,栈是后进先出

注意--区别栈区和堆区。堆区的存取是顺序随意,而栈区是后进先出。栈由编译器自动分配释放,存访函数的参数值,局部变量的值等。其操作方式类似于数据结构中的。堆一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。分配方式类似于链表。

22.设置地址为0x68a9的整数变量的值为0xa66

int *ptr;

ptr = (int *)0x67a9;

*ptr = 0xaa66;

注意--无论在什么平台地址长度和整型数据的长度是一样的,即一个整数型可以强制转换成地址指针类型

23.C语言的结构体与C++的区别

1.c语言的结构体不能有函数成员的,C++类是有的

2.C语言的结构体数据成员是没有private、public和protected访问限定的,而C++类成员有这些访问限定

3.C语言的结构体是没有继承关系的,而C++有着丰富的继承关系

注意--虽然C的结构体和C++的类有很大的相似度,但是类是实现面向对象的基础。而结构体只可以简单的理解为类的前身。

24.如何有效的避免野指针

指针变量声明时没有初始化----解决办法是指针声明初始化,,可以是具体的地址值,也可以让它指向NULL

指针p被free或者delete之后,没有置为NULL----解决办法是指针指向的内存空间被释放后指针应该指向NULL

指针操作超越了变量的作用范围----解决办法是在变量的作用域结束前释放掉变量的地址空间并且让指针指向NULL

25.extern"C"

extern"C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern"C"后,会指示编译器这部分 代码按C语言的方式进行编译。由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名,而C语言并不支持函数重载,因此C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。

26.C++中strcut和class的区别

在C++中,class和struct做类型定义存在着两点区别

1.默认继承权限不同,class继承默认的是private继承,而struct默认的是public继承

2.class还可以用于定义模板参数,像typename,但是关键字struct不能同于定能一模板参数C++保留struct关键字的原因是--保证与C语言的向下兼容性。

27.C++类内可以定义引用数据成员吗

可以,必须通过成员函数初始化列表初始化

28.C++中类成员的访问权限

C++通过private、public和protected三个关键字来控制成员变量和成员函数的访问权限,它们分别表示私有的、公有的与受保护的访问限定符。在类的内部,无论成员被声明为private、public和protected,都是可以互相访问的,没有访问权限的限制。在类的外部,只能通过对象访问成员,并且通过对象只能访问public属性的成员,不能访问private、protected属性的成员。

29.什么是右值引用,跟左值有什么区别

左值和右值的概念-左值:能取地址,或者具名对象,表达式结束后依然存在的持久对象;右值:不能取地址,匿名对象,表达式结束后就不再存在的临时对象。它们之间的区别在--左值能寻址,右值不能;左值能赋值,右值不能;左值可变,右值不能

30.面向对象的三大特征

封装性--将客观事物抽象成类,每个类自身的数据和方法实行private、public和protected

继承性--广义的继承有三种实现形式:实现继承-使用基类的属性和方法,可视继承--子窗体使用父窗体,接口继承--仅仅使用属性和方法

多态性--将父类对象设置成为一个或多个它的子对象相等的技术。用子类对象给父类对象赋值之后,父类对象就可以根据当前赋值给它的子对象的特性以不同的方式运作

31.C++中的四种cast转换

C++中四种类型的转换是-static_cast,dynamic_cast,const_cast,reinterpret_cast

const_cast--将const变量转为非const

static_cast--用于各种隐式转换,用于非多态类型转换,不执行运行时类型检查,通常用于转换数值数据类型,可以在整个类层次结构中移动指针,子类转化为父类安全。

dynamic_cast--用于动态类型转换,只能用于含有虚函数的类,用于类层次间的向上和向下转换。只能转指针或引用

reinterpret_cast--几乎什么类型都可以进行转换

32.拷贝构造函数和赋值运算符的认识

拷贝构造函数和赋值运算符重载有以下两个不同之处

1.拷贝构造函数生成新的类对象,而赋值运算符不能

2.由于拷贝构造函数是直接构造一个新的类对象,所以在初始化这个对象之前不用检验源对象是否和新建对象相同。而赋值运算符则需要这个操作,另外赋值运算中如果原来的对象中有内存分配要先把内存释放掉

注意--当有类中有指针类型的成员变量时,一定要重写拷贝构造函数和赋值运算符

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值