原文作者:aircraft

原文链接:https://www.cnblogs.com/DOMLX/p/10713204.html

一套面试题的目录在此,还在继续完善中。。。。。。

c/c++ 2019面试题目录

1.利用指针交换两个字符串方法?(这题是我当年读大一的时候看到的,好怀念!!!QAQ)

(一)指针引用

#include<iostream>
using namespace std;
void swap(char *&a,char *&b)
{
char *temp;
temp = a;
a = b;
b = temp; }
int main()
{
char *ap = "hello";
char *bp = "word"; swap(ap,bp); cout<<"ap:"<<ap<<endl;
cout<<"bp:"<<bp<<endl; return ;
}

(二)二维指针指向一维

#include<iostream>
using namespace std;
void swap(char **a,char **b)
{
char *temp;
temp = *a;
*a = *b;
*b = temp; }
int main()
{
char *ap = "hello";
char *bp = "word"; swap(&ap,&bp); cout<<"ap:"<<ap<<endl;
cout<<"bp:"<<bp<<endl; return ;
}

2.参数引用--查找下面程序错误

#include<iostream>
using namespace std; const float pi = 3.14f;
float f; float f1(float r)
{
f = r*r*pi;
return f;
} float &f2(float r)
{
f = r*r*pi;
return f;
}
int main()
{
float f1(float=);
float &f2(float=);
float a = f1();
float &b = f1(); //虽然返回的好像是一个全局变量,但是函数在处理的时候
//编译器机制返回的依然是一个临时建立的temp变量里面存放的是f内的值,对其进行引用报错
float c = f2();
float &d = f2();//函数定义返回值的时候加了引用,此时不会生成临时变量
//直接返回全局变量f,这种定义最节省空间,但是要注意全局变量f生存周期要大于引用d
//这里是安全的 d += 1.0f; cout<<"a:"<<a<<endl;
cout<<"b:"<<b<<endl;
cout<<"c:"<<c<<endl;
cout<<"d:"<<d<<endl;
cout<<"f:"<<f<<endl; return ;
}

3.下面输出是什么?

 int a[]={,,,,};
int *ptr=(int *)(&a+);
printf("%d,%d/n",*(a+),*(ptr-));

答案:输出:2,5
  *(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5
  &a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int)
  &a是数组指针,其类型为 int (*)[5];

4.复杂的指针声明

简单级别:

a-一个整型数

b-一个指向整型数的指针

c-一个指向指针的指针,它指向的指针是指向一个整型数的

d-一个有十个整型数的数组

e-一个有十个指针的数组,该指针指向一个整型数

f-一个指向十个整型数数组的指针

g-一个指向函数的指针,该函数有一个整型参数并返回一个整型数

答案:

a: int a;
b: int *a;
c: int **a;
d: int a[];
e: int *a[];
f: int (*a)[];
g: int (*a)(int);

复杂级别:

a-一个有十个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数

b-func是一个指向数组的指针,这个数组的元素是函数指针,这些指针指向有int*类型的形参,返回值为Int类型的函数

c-func是一个函数指针,这类函数具有int*类型的形参,返回值是指向数组的指针,所指向的元素是5个int元素的数组

答案:

a: int (*a[])(int);
b: int (*(func)[])(int *p);
c: int(*(func)(int *p))[];

5.指针数组与数组指针(这个大一刚学的时候真的很混乱!!)

(不管是数组指针还是指针数组,像这像的词前半区都是修饰词,修辞后面,数组指针本质是个指针,指向一个数组。指针数组本质是个数组,数组里存放的是指针)

---同理:指针常量和常量指针。函数指针和指针函数都可以这么理解

数组指针(也称行指针)
定义 int (*p)[n];
()优先级高,首先说明p的本质是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。

如要将二维数组赋给一指针,应这样赋值:
int a[3][4];
int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。
 p=a;        //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
 p++;       //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]

所以数组指针也称指向一维数组的指针,亦称行指针。

指针数组
定义 int *p[n];
[]优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,它有n个指针类型的数组元素。这里执行p+1时,则p指向下一个数组元素,这样赋值是错误的:p=a;因为p是个不可知的表示,只存在p[0]、p[1]、p[2]...p[n-1],而且它们分别是指针变量可以用来存放变量地址。但可以这样
*p=a; 这里*p表示指针数组第一个元素的值,a的首地址的值。
如要将二维数组赋给一指针数组:
int *p[3];
int a[3][4];
p++; //该语句表示p数组指向下一个数组元素。注:此数组每一个元素都是一个指针
for(i=0;i<3;i++)
p[i]=a[i]
这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2]
所以要分别赋值。

这样两者的区别就豁然开朗了,数组指针只是一个指针变量,似乎是C语言里专门用来指向二维数组的,它占有内存中一个指针的存储空间。指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。
还需要说明的一点就是,同时用来指向二维数组时,其引用和用数组名引用都是一样的。
比如要表示数组中i行j列一个元素:
*(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j]

优先级:()>[]>*

6.下面输出的是什么?

int main()
{
char * str[] = {"Welcome","to","Forteedia","Nanjing"} ;
char **p = str + ;
str[] = (*p++) +;
str[] = *(p+);
str[] = p[] + ;
str[] = p[] + (str[] - str[]); printf("%s\n",str[]);
printf("%s\n",str[]);
printf("%s\n",str[]);
printf("%s\n",str[]);
return ;
}
答案:
(空)
Nanjing
jing
g 其他应该没有疑问就说一下第一个空 。
char **p = str + 1; 这句指向“to”
str[0] = (*p++) +2;这里(*p++),p本身为一个二维指针,*号已经是指向一维。++不管是这行执行完后自加
这里如果是*p+1的话那么str【0】输出的是“o”,
也就是*p指向“to”的t,*p+1指向o,*p+2指向“to”之后的不存在区,为空
代码逻辑表示为str[1][2];而“to”这里只有str[1][0],str[1][1]; 觉得自己完全理解这题的指针知识点了吗,那么p[1]+3这行执行完毕p[0]为什么指向‘j’了呢?
可以在评论区写出你的回答,也可以关注我,下篇做出解释,hhhhh
 

7.代码改错-函数指针的使用(下面代码有什么问题?打印三个数中最大者)

#include<iostream>
using namespace std; int max(int x,int y)
{
return x>y?x:y;
} int main()
{
int *p;
int a,b,c;
int result;
int max(x,y); p=max;
cout<<"please input three integer"<<endl;
cin>>a>>b>>c;
result = (*p)((*p)(a,b),c);
cout<<"result= "<<relust<<endl; return ;
}
答案:
#include<iostream>
using namespace std; int max(int x,int y)
{
return x>y?x:y;
} int main()
{
int (*p)(int,int); //改正 定义一个函数指针,才能指向一个函数
int a,b,c;
int result;
int max(int,int); //改正 声明函数是写形参的类型 p=&max;
cout<<"please input three integer"<<endl;
cin>>a>>b>>c;
result = (*p)((*p)(a,b),c);
cout<<"result= "<<result<<endl; return ;
}

8.typedef用于函数指针定义

下面的定义有什么作用?

typedef int (*pfun)(int,int);

这里的pfun是一个使用typedef的自定义数据类型。意思就是:定义了一种pfun的类型,并定义这种类型为指向某种函数的指针,这种函数以两个个int为参数并返回int类型。

这样的话定义函数指针什么的就很方便了。

使用方法:

#include<iostream>
using namespace std; typedef int (*pfun)(int,int);
int fun(int x,int y)
{
return (x+y);
}
int main()
{
int fun(int,int);
pfun p = fun; //注意 pfun是类型 类型定义变量
int ret = p(,);
cout<<ret<<endl; return ;
}

9.什么是“野指针”?

“野指针”不是NULL指针,而是指向”垃圾”内存的指针。其成因主要为:指针变量没有被初始化,或者指针p被free或者delete之后没有置为NULL

10.有了malloc/free为什么还要new 和delete

  malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。

对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。

因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。

我们先看一看malloc/free和new/delete如何实现对象的动态内存管理,见下列代码。

class Obj
{
public :
Obj(void){ cout << "Initialization" << endl; }
~Obj(void){ cout << "Destroy" << endl; }
void Initialize(void){ cout << "Initialization" << endl; }
void Destroy(void){ cout << "Destroy" << endl; }
}; void UseMallocFree(void)
{
cout<<"use mallocFree。。"<<endl;
Obj *a = (obj *)malloc(sizeof(obj)); // 申请动态内存
free(a); // 释放内存
} void UseNewDelete(void)
{
cout<<"use newFree。。"<<endl;
Obj *a = new Obj; // 申请动态内存并且初始化 delete a; // 清除并且释放内存
}
int main()
{
UseMallocFree();
UseNewDelete(); return ;
}

打印结果如下:

use mallocFree。。

use newFree。。

Initialization

Destroy

 

对于非内部数据类型的对象而言,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器的控制权限之内,不能把执行构造函数和析构函数的任务强加于malloc/free,因此只有使用new/delete运算符

11.比较分析两个代码段的输出,错误点在哪--(动态内存的传递)

代码段一

char * getMemory()
{
char p[] = "hello";
return p;
} void Test(void)
{
char *str = NULL;
str = getMemory();
printf(str);
}

代码段二

void getMemory()
{
p = (char*)malloc();
} void Test(void)
{
char *str = NULL;
getMemory(str);
strcpy(str,"hello");
printf(str);
}

代码段一:栈内存分配,函数结束自动销毁,输出乱码。

代码段二:此时的函数形参只是个复制体,不能传递动态内存给实参。并且函数结束后丢失堆内存地址,不能释放,导致内存泄漏。

本篇是第二篇面试题总结,后面还有好多篇,想要剑指offer的关注我把!!!

若有兴趣交流分享技术,可关注本人公众号,里面会不定期的分享各种编程教程,和共享源码,诸如研究分享关于c/c++,python,前端,后端,opencv,halcon,opengl,机器学习深度学习之类有关于基础编程,图像处理和机器视觉开发的知识

c++面试题中经常被面试官面试的小问题总结(二)(本篇偏向指针知识)的更多相关文章

  1. c++面试题中经常被面试官面试的小问题总结(一)(本篇偏向基础知识)

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/10711810.html 1.类中的函数定义后加了一个const代表什么? 代表它将具备以下三个 ...

  2. 存在一个足够大的二维数组,每个数组中的值都是整数,使用javascript如何实现按每个数组中的平均值,从大到小排序这个二维数组?

    这是牛客网上的一道题~ 题意:对数组排序,顺序是按照数组的平均值,即按照一个元素和平均值相减的绝对值的大小来排序...本例按这个绝对值递增排序 解题思想:先求出这个数组的平均值,如果 a<b,那 ...

  3. 面试官:说一说Zookeeper中Leader选举机制

    哈喽!大家好,我是小奇,一位不靠谱的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 今天又是一个阳光明媚的一天,我又 ...

  4. 想入职阿里的Java开发者必看,阿里巴巴面试官实战经验分享!

    最近社区Java技术进阶群的小伙伴总是会问,如何面试阿里Java技术岗,需要什么条件,做哪些准备:小编就这些问题找到了阿里技术团队中在一线真正带Java开发团队并直接参与技术面试的专家,分享了自身在筛 ...

  5. 面试官问我redis数据类型,我回答了8种

    面试官:小明呀,redis 有几种数据结构呀? 小明:8 种 面试官:那你说一下分别是什么? 小明:raw,int,ht,zipmap,linkedlist,ziplist,intset,skipli ...

  6. 面试官问我MySQL索引,我

    面试官:我看你简历上写了MySQL,对MySQL InnoDB引擎的索引了解吗? 候选者:嗯啊,使用索引可以加快查询速度,其实上就是将无序的数据变成有序(有序就能加快检索速度) 候选者:在InnoDB ...

  7. 面试官一口气问了MySQL事务、锁和MVCC,我

    面试官:你是怎么理解InnoDB引擎中的事务的? 候选者:在我的理解下,事务可以使「一组操作」要么全部成功,要么全部失败 候选者:事务其目的是为了「保证数据最终的一致性」. 候选者:举个例子,我给你发 ...

  8. 面试官问我MySQL调优,我真的是

    面试官:要不你来讲讲你们对MySQL是怎么调优的? 候选者:哇,这命题很大阿...我认为,对于开发者而言,对MySQL的调优重点一般是在「开发规范」.「数据库索引」又或者说解决线上慢查询上. 候选者: ...

  9. 面试官:为什么需要Java内存模型?

    面试官:今天想跟你聊聊Java内存模型,这块你了解过吗? 候选者:嗯,我简单说下我的理解吧.那我就从为什么要有Java内存模型开始讲起吧 面试官:开始你的表演吧. 候选者:那我先说下背景吧 候选者:1 ...

随机推荐

  1. prog1,2,3

    1.第一版本程序Prog1:+ 给定一个数组,实现数组元素求和:具体要求:实现对一维数组(a[100])的所有元素相加运算.+ 数据准备:a)数组长度:100:b)数组数据来源:实验数据A列:1~10 ...

  2. IDEA配置spring

    大半天都在看spring,以前总是看不下去,这次慢慢来,慢慢看. 看那些基础的,倒是还不错.好多都是关于helloworld的,写完helloworld,觉得不怎么形象.于是写了动物,作为接口. (1 ...

  3. linux 常用命令,开发记住这些基本能够玩转linux

    系统信息 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMBIOS ...

  4. you need to be root to perform this command

    在linux 终端执行某条命令时 提示一下错误 you need to be root to perform this command 是提示要获取root权限 输入su 回车输入密码 即可解决 参考 ...

  5. 操作XDocument讲解

    1.首先建立好XML .可以通选自定义EXCEL导出XML格式的数据:(如图) 2 读取XML 文件 具体的详细讲解 可以查看 改网址 :https://blog.csdn.net/dyllove98 ...

  6. ES6——异步操作之Promise

    基本概念: Promise : 是 ES6 中新增的异步编程解决方案,提现在代码中他是一个对象 可以通过Promise构造函数来实例化. -new Promise(cb) ===> 实例的基本使 ...

  7. c#去除DataTable空列

    网上搜了好多,没找到能用的,自己写一个,有发现错误的给我留言. private void RemoveNULLColumns(ref DataTable data)//删除空列 { try { Dat ...

  8. MongoDB .Net Driver(C#驱动) - 内嵌数组/嵌入文档的操作(增加、删除、修改、查询(Linq 分页))

    目录 一.前言 1. 运行环境 二.前期准备工作 1. 创建 MongoDBContext MongoDb操作上下文类 2.创建测试类 3.创建测试代码 三.内嵌数组增加元素操作 1.Update.S ...

  9. how to trace the error log

    Executed as user: WTC\Ebw.Admin. Transaction (Process ID 95) was deadlocked on lock resources with a ...

  10. JS获取节点属性个数及值得方法

    var ex = node; ; for (var j in ex) { alert("" + myIndex + ".(<font color='blue'> ...