网站建设七点,网站浏览量提升,网站建立的步骤是,网站代做1.new与malloc的区别
new操作符从自由存储区上为对象动态分配内存空间#xff0c;而malloc函数从堆上动态分配内存。
使用new操作符申请内存分配时无须指定内存块的大小#xff0c;而malloc则需要显式地指出所需内存的尺寸。
int *p new int;
delete p;//一定要配对使用n…1.new与malloc的区别
new操作符从自由存储区上为对象动态分配内存空间而malloc函数从堆上动态分配内存。
使用new操作符申请内存分配时无须指定内存块的大小而malloc则需要显式地指出所需内存的尺寸。
int *p new int;
delete p;//一定要配对使用new 和 delete
int *p new int [10];//对于数组应使用另一种格式的delete来释放
delete [] p; int *p (int *)malloc(sizeof(int));*p 100;free(p);p NULL;return 0;
2.malloc/free 为什么还要 new/delete
malloc 与 free 是 C/C 语言的标准库函数new/delete 是 C的运算符。它们都可用于申请动态内存和释放内存。 对于非内部数据类型的对象而言
光用 maloc/free 无法满足动态对象的要求。对象在创建的同时要自动执行构造函数对象在消亡之前要自动执行析构函数。由于malloc/free 是库函数而不是运算符
不在编译器控制权限之内不能够把执行构造函数和析构函数的任务强加malloc/free。 因此 C语言需要一个能完成动态内存分配和初始化工作的运算符 new
以及一个能完成清理与释放内存工作的运算符 delete。注意 new/delete 不是库函数。
3.delete与 delete []区别
delete只会调用一次析构函数而delete[]会调用每一个数组元素的析构函数。
delete与new配套delete []与new []配套。
4.在物理内存为1G的计算机中能否malloc(1.2G)
在支持虚拟内存管理的操作系统上当请求的内存大于128kbmalloc()会调用mmap()分配一起分配内存。
在不支持虚拟内存管理的实时操作系统上运行这种情况下在只有1G物理内存的计算机上malloc1.2G就会失败。
5.用C写个程序如何判断一个操作系统是16位还是32位的
定义一个指针p打印出sizeof( p ),如果节后是4则表示该操作系统是32位打印结果是2表示是16位。
6.解释下位域为什么要用位域位域的好处
在计算机中有些信息存储时并不需要占用一个完整的字节而只需占用一个或几个二进制位。比如在存放一个只有0和1两种状态的开关量时
用一位二进制位即可表示。因此为了节省存储空间C语言提供了一种称为“位域”的数据结构来充分利用存储空间。
7.位操作
位与符号是一个两个是逻辑与位或符号是一个|两个||是逻辑或。
C语言中按位取反是~C语言中的逻辑取反是!。
左移位与右移位
对于无符号数左移时右侧补0相当于逻辑移位,右移时左侧补0相当于逻辑移位 对于有符号数左移时右侧补0叫算术移位相当于逻辑移位,右移时左侧补符号位如果正数就补0负数就补1叫算术移位 嵌入式中研究的移位以及使用的移位都是无符号数.
https://blog.csdn.net/weixin_49303682/article/details/118662325
8.在某工程中要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。
int *p;
p (int *)0x67a9;
*p 0xaa66;
9.给定一个整型变量a写两段代码第一个设置a的bit3第二个清除a的bit在以上两个操作中要保持其它位不变。 #define BIT3 (0x13)static int a;void set_bit3(void){a | BIT3;}void clear_bit3(void){a ~BIT3;}
10.什么是右值引用跟左值又有什么区别
左值能对表达式取地址一般指表达式结束后依然存在的持久对象。
右值不能对表达式取地址一般表达式结束后就不再存在的临时对象。
11.判断xx1,x1,x哪个效率最高?为什么?
x的效率最高直接去出来1后在放回原来的地址。
xx1最低, 因为执行步骤如下: 1读取右x的地址; 2x1; 3读取左x的地址4将右值传给左边的x(编译器并不认为左右两边的x的地址相同)。
12.用变量a定义
一个整型数 int a; 一个指向整型数的指针 int *a; 一个指向指针的指针它指向的指针式指向一个整型数 int **a; 一个有10个整型数的数组 int a[10]; 一个有10指针的数组该指针是指向一个整型数 int *a[10]; 一个指向有10个整型数数组的指针 int (*a)[10]; 一个指向函数的指针该函数有一个整型数参数并返回一个整型数 int (*a)(int); 一个有10个指针的数组该指针指向一个函数该函数有一个整型数参数并返回一个整型 int (*a[10])(int);
13.C语言是强类型的语言这是什么意思
C语言是一种强类型的程序设计语言int x,y,z;在C程序中每一个变量都必须声明其取值类型。
char 占8位1字节short占16位2字节int 占32位4字节long 占32位4字节float占32位4字节double占64位8字节。
14.char 与 int之间的转换
从长字节数据类型转换为短字节数据类型会产生截断从4字节的int类型转换成1个字节的char类型则取int数据的最低的一个字节。
从短字节类型转换为长字节类型从char转换为int则在前面的三个字节补符号位0x000000。
15.float单精度浮点型和double双精度浮点型
float:1bit(符号位)8bit(指数位)23尾数位 2^238388608共7位意味着最多有7位有效数字。
double:1bit(符号位)11bit指数位52bit(尾数位) 2^524503599627370496. 一共16位同理double的精度为15~16位。 #include stdio.hint main(void){float m (float)3.14;double n 10.5;printf(%f,%lf\n,m,n);return 0;}
输出3.140000,10.500000 因为%lf只保留小数点后6位。
16.字符常量
char beta; beta’ab’; 是错误的改正char beta; beta’ab/’
char beta; beta”a”; 是错误的改正char beta; beta’a’
定义字符串数组char a[ ] abcse
非图形字符如退格换行也可以表示成字符型常量。表示方法是使用转义字符”/”;
已知char b[5],*pb; 则正确的赋值语句是 C
A. b“abcd” ; B. *b“abcd”; C. p“abcd”; D. *p“abcd”;
下列可以正确表示字符型常量的是 D
A、297 B、a C、\n D、\t
17.写出bool 、int、 指针变量与“零值”比较的if语句
bool型数据
if( flag ) { A; } else { B }
int型数据
if( 0 ! flag ) { A; } else { B }
指针型数
if( NULL flag ) { A; } else { B }
18.写出float x 与“零值”比较的if语句。
if(x0.000001x-0.000001)
19.区分 %d, %ld, %lld, %lf, %f
%dint,
%ldlong,
%lldlong long;
在32位编译器上intlong32bitlong long64bit。
输入时
float 输入用 %f小数点后6位。
double 输入用 %lf小数点后6位。
20.输出数据问题
printf(“%d\n”,101010); 默认的方式是左对齐。
printf(“%-10d\n”,101010); 在打印数字宽度前面加一个“-”也是左对齐10表示数字宽度为10其他空格补齐。
printf(“%10d”,101010); 在%和d之间加上数字宽度就可以右对齐了10表示数字宽度为10其他空格补齐。 double a 326.3845;printf(%10.3f\n, a); 结果是326.385注意前面是有空格的 printf(%04d, 3); 结果为0003
21.嵌入式系统中经常要用到无限循环你怎么样用C编写死循环 while(1){;} for(;;){;}
22.惰性计算方法 #include stdio.hvoid main(){int n 2, k 0;while(kn2);printf(%d %d\n,k,n);} 输出的正确答案是1 2
刚开始运算的时候k的值是0n的值是2并还没有进行自增1的操作自增1要在下一次循环中。对于循环条件(kn2)
首先计算k由于k的初值为0k是后坐因此k在参与比较的时候是0假比较以后k值增1变为1这时系统不会再计算后面的表达式了即
所谓的惰性计算方法所以n2没有参与运算也就是说循环语句执行之后k的值是1n的值是2.
23.变量的声明和定义有什么区别
为变量分配地址和存储空间的称为定义不分配地址的称为声明。一个变量可以在多个地方声明但是只在一个地方定义。
加入extern修饰的是变量的声明说明此变量将在文件以外或在文件后面部分定义。
24.用预处理指令#define 声明一个常数用以表明1年中有多少秒(忽略闰年问题)
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
25.写一个“标准”宏MIN这个宏输入两个参数并返回较小的一个 #define MIN(a, b) (a) (b) ? (a) : (b)
26.sizeof和strlen的区别
sizeof的参数可以是数据的类型也可以是变量而strlen只能以结尾为‘\0‘的字符串作参数。
sizeof计算的是数据类型占内存的大小而strlen计算的是字符串实际的长度。
27.c语言中的static和C中static的区别
static在C语言中具有记忆性隐藏性初始化为0的特点。
而C中除了上述功能外还用来定义类的成员变量和函数。即静态成员和静态成员函数。
28.C函数中值的传递方式有哪几种?
C函数的三种传递方式为值传递、指针传递和引用传递。
29.C里面是不是所有的动作都是main()引起的如果不是请举例。
比如全局变量的初始化就不是由main函数引起的。举例 class A{}; A a; //a的构造函数限执行 int main() {}
30.谈谈对面向对象的认识
面向对象可以理解成对待每一个问题都是首先要确定这个问题由几个部分组成而每一个部分其实就是一个对象。
然后再分别设计这些对象最后得到整个程序。传统的程序设计多是基于功能的思想来进行考虑和设计的而面向对象的
程序设计则是基于对象的角度来考虑问题。这样做能够使得程序更加的简洁清晰
31.谈谈你对编程规范的理解
编程规范可总结为程序的可行性可读性、可移植性以及可测试性。
说明这是编程规范的总纲目面试者不一定要去背诵上面给出的那几个例子应该去理解这几个例子说明的问题
想一想自己如何解决可行性、可读性、可移植性以及可测试性这几个问题结合以上几个例子和自己平时的编程习惯来回答这个问题。
32.面向对象的三大特性 面向对象的三大特征是封装性、继承性和多态性
封装性将客观事物抽象成类每个类对自身的数据和方法实行protectionprivate protectedpublic。
继承继承主要实现重用代码节省开发时间子类可以继承父类的属性和方法。
多态性是将父类对象设置成为和一个或更多它的子对象相等的技术。用子类对象给父类对象赋值之后父类对象就 可以根据当前赋值给它的子对象的特性以不同的方式运作。
33.简述多态的原理 编译器发现一个类中有虚函数便会立即为此类生成虚函数表 vtable。虚函数表的各表项为指向对应虚函数的指针。
编译器还会在此类中隐含插入一个指针vptr对vc编译器来说它插在类的第一个位置上指向虚函数表。调用此类的构造函数时
在类的构造函数中编译器会隐含执行vptr与vtable的关联代码将vptr指向对应的vtable将类与此类的vtable联系了起来。
另外在调用类的构造函数时指向基础类的指针此时已经变成指向具体的类的this指针这样依靠此this指针即可得到正确的vtable。
如此才能真正与函数体进行连接这就是动态联编实现多态的基本原理。
34.多态的作用
主要是两个1隐藏实现细节使得代码能够模块化扩展代码模块实现代码重用
2接口重用为了类在继承和派生的时候保证使用家族中任一类的实例的某一属性时的正确调用。
35.多态虚函数纯虚函数
多态是对于不同对象接收相同消息时产生不同的动作。
虚函数在基类中冠以关键字 virtual 的成员函数。 它提供了一种接口界面。允许在派生类中对基类的虚函数重新定义。
纯虚函数的作用在基类中为其派生类保留一个函数的名字以便派生类根据需要对它进行定义。作为接口而存在纯虚函数不具备函数的功能一般不能直接被调用。
具有纯虚函数的类是抽象类abstract class不能声明对象只能作为基类为派生类服务除非派生类完全实现了基类的所有纯虚函数否则派生类也成为抽象类不能
声明对象。
36.重载overload)、重写(override有的书也叫做“覆盖”、重定义redefinition的区别?
重载同一名字子空间是指允许存在多个同名函数而这些函数的参数表不同。重定义/隐藏不同名字子空间用于继承派生类与基类的函数同名屏蔽基类的函数重写/覆盖不同名字子空间用于继承子类重新定义父类虚函数的方法
37.所有的运算符都能重载吗
不能被重载的运算符
在 C运算符集合中有一些运算符是不允许被重载的。这种限制是出于安全方面的考虑可防止错误和混乱。
1不能改变 C内部数据类型如 int,float 等的运算符。
2不能重载‘.’因为‘.’在类中对任何成员都有意义已经成为标准用法。
3不能重载目前 C运算符集合中没有的符号如#,,$等。原因有两点一是难以理解二是难以确定优先级。
4对已经存在的运算符进行重载时不能改变优先级规则否则将引起混乱。
38.用C设计一个不能继承的类 template typename T class A { friend T; private: A() {} ~A() {} }; class B : virtual public AB { public: B() {} ~B() {} }; void main( void ) { B b; return;
}
39.构造函数能否为虚函数
构造函数不可以析构函数可以。
因为对象中的虚函数表指针是在构造函数初始化列表阶段才初始化的。
如果它的构造函数是虚函数那就要通过对象中的虚函数表指针来调用而这个虚函数表是在构造函数初始化列表阶段才初始化的。
https://blog.csdn.net/qq_41830537/article/details/102626648
40.在C中用const 能定义真正意义上的常量吗C中的const呢
const修饰的变量是只读的本质上还是变量与C语言不同c中的const不是只读变量。C中的const是个真正意义上的常量。
C语言中的const还是可变的 int main(){const int c 0;int* p (int*)c; printf(Begin...\n); *p 5;printf(c %d\n, c); //C语言编译输出5//说明c并不是真正意义上的常量 return 0;}
由于c中const常量的值在编译期就已经决定下面的做法是OK的但是c中是编译通不过的。
int main(void){const int a 8;const int b 2;int array[ab] {0};return 0;
}
41.宏和内联inline函数的比较
(1)内联inline函数是C中引用的一个新的关键字C中推荐使用内联函数来替代宏代码片段
(2)内联函数将函数体直接扩展到调用内联函数的地方这样减少了参数压栈跳转返回等过程
(3) 由于内联发生在编译阶段所以内联相较宏是有参数检查和返回值检查的因此使用起来更为安全
(4)内联函数不能过于复杂最初C限定不能有任何形式的循环不能有过多的条件判断不能对函数进行取地址操作等
但是现在的编译器几乎没有什么限制基本都可以实现内联。
42.typedef和define由什么区别
用法不同typedef用来定义一种数据类型的别名增强程序的可读性。define主要用来定义常量以及书写复杂使用频繁的宏。
执行时间不同typedef是编译过程的一部分有类型检查的功能。define是宏定义是预编译的部分其发生在编译之前只是简单的进行字符串的替换不进行类型的检查。
https://blog.csdn.net/qq_45607873/article/details/123746610
43.strcat、strncat、strcpy哪些函数会导致内存溢出如何改进
strcpy函数会导致内存溢出。
strcpy拷贝函数不安全他不做任何的检查措施也不判断拷贝大小不判断目的地址内存是否够用。
char *strcpychar *strDestconst char *strSrc
strncat()主要功能是在字符串的结尾追加n个字符。
char * strncat(char *dest, const char *src, size_t n);
strcat()函数主要用来将两个char类型连接。例如
char d[20]Golden;
char s[20]View;
strcat(d,s); //打印d printf(%s,d);
输出 d 为 GoldenView 中间无空格
**延伸**
memcpy拷贝函数它与strcpy的区别就是memcpy可以拷贝任意类型的数据strcpy只能拷贝字符串类型。
memcpy 函数用于把资源内存src所指向的内存区域拷贝到目标内存dest所指向的内存区域
有一个size变量控制拷贝的字节数
函数原型
void *memcpy(void *dest, void *src, unsigned int count);
44.简述队列和栈的异同
队列和栈都是线性存储结构但是两者的插入和删除数据的操作不同队列是“先进先出”栈是“后进先出”。
45.堆和栈的区别
堆存放动态分配的对象——即那些在程序运行时动态分配的对象比如 malloc出来的对象其生存期由程序控制必须手动申请手动释放。
栈用来保存定义在函数内的非static对象如局部变量仅在其定义的程序块运行时才存在由编译器自动创建和销毁。
46.堆和自由存储区的区别
总的来说堆是C语言和操作系统的术语是操作系统维护的一块动态分配内存自由存储是C中通过new与delete动态分配和释放对象的抽象概念。他们并不是完全一样。
从技术上来说堆heap是C语言和操作系统的术语。堆是操作系统所维护的一块特殊内存它提供了动态分配的功能当运行程序调用malloc()时就会从中分配
稍后调用free可把内存交还。而自由存储是C中通过new和delete动态分配和释放对象的抽象概念通过new来申请的内存区域可称为自由存储区。
47.什么是内存泄漏面对内存泄漏有什么避免方法
用动态存储分配函数动态开辟的空间在使用完毕后未释放结果导致一直占据该内存单元即为内存泄露。
malloc的时候得确定在那里free. new的时候得确定delete。在C中应该优先考虑使用智能指针.
48.链表和数组的区别
存储形式数组是一块连续的空间声明时就要确定长度。链表是一块可不连续的动态空间长度可变每个结点要保存相邻结点指针。
数据查找数组的线性查找速度快查找操作直接使用偏移地址。链表需要按顺序检索结点效率低。
数据插入或删除链表可以快速插入和删除结点而数组则可能需要大量数据移动。
越界问题链表不存在越界问题数组有越界问题。
49.结构与联合有和区别
在使用结构变量时要先对其定义 结构名是结构的标识符不是变量名结构是按变量名字来访问成员的结构体指针采用“-”访问成员结构体变量采用“.”访问。
结构和联合都是由多个不同的数据类型成员组成, 但在任何同一时刻, 联合中只存放了一个被选中的成员所有成员共用一块地址空间, 而结构的
所有成员都存在不同成员的存放地址不同。
对于联合的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于结构的不同成员赋值是互不影响的。
50.什么是“引用”申明和使用“引用”要注意哪些问题
引用就是某个目标变量的“别名”(alias)对应用的操作与对变量直接操作效果完全相同。
声明一个引用不是新定义了一个变量它只表示该引用名是目标变量名的一个别名它本身不是一种数据类型因此引用本身不占存储单元系统也不给引用
分配存储单元。不能建立数组的引用。
51.将“引用”作为函数参数有哪些特点
传递引用给函数与传递指针的效果是一样的。这时被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用所以在被调函数中对形参变量的
操作就是对其相应的目标对象在主调函数中的操作。
使用引用传递函数的参数在内存中并没有产生实参的副本它是直接对实参操作.
52.STL标准模板库
vector单端数组当现有的内存空间不够装下数据时首先配置一块新的空间然后将旧空间的数据搬往新空间再释放原来的空间。
deque双端数组可以在头尾两端分别做元素的插入和删除操作除非必要应尽可能的选择使用vector而非deque因为 deque的迭代器比vector的迭代器要复杂的多。
list双向链表相较于vector的连续线性空间list就显得负责许多它的好处是每次插入或者删除一个元素就是配置或者释放一个元素的空间适合频繁的不确实位置元素
的移除插入。
set二叉树map二叉树底层实现都是 红黑树它可以在O(logn)时间内高效的做查找插入和删除。
53.陷阱题 int main(){int j2;int i1;if(i 1) j3;if(i 2) j5;printf(%d,j);} 输出为5如果再加上if(i3)j6;则输出6。
int main(void)
{unsigned int a 6;int b -20;char c;(ab6)?(c1):(c0);
}则c1但ab-14;如果a为int类型则c0。原来有符号数和无符号数进行比较运算时,,,,有符号数隐式转换成了无符号数即底层的补码不变但是此数从有符号数变成了无符号数比如上面 (ab)6这个比较运算ab-14-14的补码为1111111111110010。此数进行比较运算时被当成了无符号数它远远大于6所以得到上述结果。 main(){int a[5]{1,2,3,4,5};int *ptr(int *)(a1);//a相当于变成了行指针加1则变成了下一行首地址printf(%d,%d,*(a1),*(ptr-1));}*(a1就是a[1]*(ptr-1)就是a[4],执行结果是25
int main()
{char a;char *stra;strcpy(str,hello);printf(str);return 0;}将字符串赋值给字符变量内存不够存在越界。
void test(void) {char *p null;strcpy(p,hello);printf(%s\n,p);}段错误野指针问题
wap( int* p1,int* p2 ){int *p;*p *p1;*p1 *p2;*p2 *p;}段错误p没有空间为其分配空间或者不使用指针 char *RetMenory(void){char p[] “hellow world”;return p;}void Test(void){char *str NULL;str RetMemory();printf(str);}由于p[]是自动变量所以RetMenory执行完毕时资源被回收p指向未知地址。因此str的内容应是不可预测的, 打印的应该是str的地址void getmemery(char *p){p (char *)malloc(100);}main(){char *str NULL;getmemery(str);strcpy(str,hello world!);printf(%s\n,str);} 段错误问题出在这上述代码传入getmemery(char *p)函数的字符串指针是形参在函数内部修改形参并不能真正的改变传入形参的值执行完char *str NULL; gememory(str);后的str仍为NULL一般函数的传递都是值传递不会改变函数外的变量值。简单地说就是形参不能够改变实参实参只是复制了一份给形参其自身并没有被改变void getmemery(char **p){*p (char *)malloc(100);}main(){char *str NULL;getmemery(str);strcpy(*str,hello world!);printf(%s\n,*str);}这就是我们常说的“地址传递”将str的地址传给getmemery()函数getmemery()函数就会通过地址修改str里面的值这样就会得到正确的结果。所以我们要记住函数传参的两种方式1值传递 2地址传递。
下面两种if语句判断方式。请问哪种写法更好为什么int n;if (n 10) // 第一种判断方式if (10 n) // 第二种判断方式【答案】这是一个风格问题第二种方式如果少了个号,编译时就会报错,减少了出错的可能行,可以检测出是否少了。
#include stdafx.h#include iostreamusing namespace std;class human {public:~human() { //析构函数,该类对象在生存期结束的时候会自动调用的一个函数cout human over...... endl;}void Disp() {cout human disp...... endl;}};class man : public human{public:~man() {cout man over...... endl;}void Disp() {cout man disp...... endl;}};int main(){human* p new man; //定义和初始化指向一个类的指针变量p-Disp(); //指向成员运算符,得到一个指针指向的元素delete p;system(pause);return 0;}答案】human disp…human over… 以下三条输出语句分别输出什么char str1[] “abc”;char str2[] “abc”;const char str3[] “abc”;const char str4[] “abc”;const char* str5 “abc”;const char* str6 “abc”;cout boolalpha ( str1 str2 ) endl; // 输出什么cout boolalpha ( str3 str4 ) endl; // 输出什么cout boolalpha ( str5 str6 ) endl; // 输出什么【答案】分别输出false,false,true。str1和str2都是字符数组每个都有其自己的存储区
它们的值则是各存储区首地址不等str3和str4同上只是按const语义它们所指向的数据区不能修改。
str5和str6并非数组而是字符指针并不分配存储区其后的“abc”以常量形式存于静态数据区而它们自己仅是指向该区首地址的指针相等。 int a5, b7, c;c ab;【答案】a6,b7,c12 一个栈的入栈序列是ABCDE则栈的不可能的输出序列是 A、EDCBAB、DECBAC、DCEABD、ABCDE【答案】C