C/C++刷题总结(1)

  1. fopen()
    “r” 打开一个用于读取的文件。该文件必须存在。
    “w” 创建一个用于写入的空文件。如果文件名称与已存在的文件相同,则会删除已有文件的内容,文件被视为一个新的空文件。
    “a” 追加到一个文件。写操作向文件末尾追加数据。如果文件不存在,则创建文件。
    “r+” 打开一个用于更新的文件,可读取也可写入。该文件必须存在。
    “w+” 创建一个用于读写的空文件。
    “a+” 打开一个用于读取和追加的文件。

r:read w:write a:add
带+都可以写入

  1. const
    const 出现在星号左边,表示的是p所指的变量内容不可变,指针指向可以改变,也就是顶层const
    const 出现在星号右边,表示的是p是一个常量指针,不能指向其他的变量,但是指向的变量的内容可以改变,底层const
    const在*左右两边都出现,表示指针指向不能改变,所指的变量内容也不能改变

类的方法后面加了const后,该方法的实现中不能修改类的成员

  1. 虚函数,动态联编,静态联编
    对于父类函数( virtual 、非 virtual ),如果有同型函数:
    ----非virtual函数由指针类型决定调用哪个 「即 f(Base &b) , 指针类型为父类Base」
    ----virtual函数由指针指向的对象决定调用哪个(运行时决定)「即 Derive obj; , 指针指向对象为子类对象Derive」

静态联编:通过对象名调用虚函数,在编译阶段就能确定调用的是哪一个类的虚函数
动态联编:通过基类指针调用,在编译阶段无法通过语句本身来确定调用哪一个类的虚函数,只有在运行时指向一个对象后,才能确定调用时哪个类的虚函数

  1. 数组指针与指针数组
    数组指针可以说成是”数组的指针”,首先这个变量是一个指针,其次,这个指针指向一个数组的首地址
char (*p)[4];
char b[4];

p指向一个char [4]的数组,不能将b赋值给p,因为b是数组首元素首地址,p存放的却是数组首地址,b是char 类型,b+1,b的值会实实在在的加1,而p是char[4]类型的,p+1,p则会加4
可以这样:p = &b,p相当与二维数组的行指针
数组指针对应着二维数组
函数定义

void fun(int (*P)[4]);//子函数中的形参,指针数组 

a[3][4] = {0};//主函数中定义的二维数组
fun(a);//主函数调用子函数的实参,是二维数组的首元素首地址

指针数组

内存映像图 内容 权限
栈区 函数中的普通变量 可读可写
堆区 动态申请的内存 可读可写
静态变量区 static修饰的变量 可读可写
数据区/常量区 用于初始化变量的常量 只读
代码区 代码指令 只读
char *a[4] = {"hello", "world", "C", "C++"};//相当于char *(a[4]),大小是16个字节

a是一个在栈区有四个元素的数组,而每一个数组又是一个指针,所以说它的四个元素各占四个字节,所以变量a的大小是16个字节。“hello”, “world”, “C”, "C++"在只读数据区。
指针数组对应的是二级指针

void fun(char **pp);//子函数中的形参
fun(char *p[]);//主函数中的实参
  1. 字符数组初始化的两种方法
    1.用字符为数组赋初值,char s[80] = {‘A’, ‘B’ ,‘C’}
    2.用字符串常量赋初值,char s[80] =“ABC”
    其他均是错误的,如char s[80]; s = {‘A’, ‘B’,‘C’},char s[80]; s = “ABC”;,此时s已经是指针了
    注意:指针指向字符串时,字符串是常量,存储在常量区,而指针存储在栈区,不能对其操作修改。
    char* s1 = “Hello world”;s1[2] = ‘E’; 这个操作是错的

  2. malloc在内存分配失败时返回的是空指针,即NULL,而不是未初始化指针。

  3. 不能再析构函数中调用delete this,否则会形成无限递归,造成堆栈溢出

  4. 二维数组初始化
    定义二维数组并赋初值时,可以省略第一维的大小,但不能省略第二维的大小,int a[2][ ]={{1,0,1},{5,2,3}}错误
    初值列表中有一行是空的,这在C语言中是不允许的,int a[][3]={{1,0,1},{},{5,2,3}}错误
    当省略第一维时,必须初始化
    int a[][5] = {};//对
    int a[][5];//错

  5. 利用循环计算
    x|(x+1)统计x二进制数中,0的个数
    x&(x-1)统计x二进制数中,1的个数

while(value)
{
    cnt++;
    //消除所有1,变成0
    value = value & (value - 1);
}

其他:

1.int x=3,y=6,z; z=x^y<<2;
先执行<<,再执行 ^
x|z&y;
先执行z&y

2.用户态切换到内核态的 3 种方式
a. 系统调用
b. 异常
c. 外围设备的中断,如read系统调用

3.对于程序需要频繁读写的少量状态数据,应该用什么存储对象
注册表是windows操作系统中的一个核心数据库,其中存放着各种参数,直接控制着windows的启动、硬件驱动程序的装载以及一些windows应用程序的运行,从而在整个系统中起着核心作用。这些作用包括了软、硬件的相关配置和状态信息

4.* 是scanf函数中的一种修饰符,表示忽略该输入项,使用方法为:放在%与格式d(或者s,c等)之间。
如选项: scanf(“%x%*d%o”,&x,&y);
scanf不能指明浮点数的精度。如果出现scanf(“%6.2f”,&x);就是错误的

注意scanf函数完全就是字符串匹配。

5.基类型相同的两个指针变量之间可以进行大小比较、赋值及减法运算,但加法运算没有意义

发布了21 篇原创文章 · 获赞 0 · 访问量 384

猜你喜欢

转载自blog.csdn.net/weixin_41605876/article/details/104777253