C/C++复习(一)

devtools/2024/10/4 12:29:22/

1.sizeof

关于sizeof我们是经常使用的,所以使用方法就不需要提及了,这里我们需要注意的是,sizeof 后面如果是表达式可以不用括号,并且sizeof实际上不参与运算,返回的是内容的类型大小(size_t类型)------sizeof是在编译时就确定结果的


2.scanf/fscanf/sscanf 与 printf/fprintf/sprintf

对于每一个学习C、C++的同学来说,区分上面的内容非常重要!!!

       

当然实际上还有snprintf这样可以读入读出n个字节的输入输出函数!!!

可以适当留意下输出的对齐符(+-)左右对齐


3.指针(重点)

        指针可以说是我们C、C++程序员最重要的知识了,所以我们必须要熟悉其全部内容

        首先,指针变量的大小与指针指向的类型无关,只与编译器环境有关(x86/x64)

区分指针数组/数组指针:

        指针数组:表示的是一个数组,但是数组的元素都是指针

        数组指针:表示一个指针,但是指向的是一个数组

联系知识:

        sizeof(arr)/&arr(arr是一个数组):表示的是对数组的整体操作,而非对数组的某个元素操作!!!

函数指针:
        规则:

        指向的函数返回类型  (*函数名)(指向的函数的参数类型与个数)

        例如:

int Add(int x,int y)
{return x+y;
}//需要注意的是:函数名可以表示函数地址int main()
{int (*pf) (int,int) =Add;//定义一个函数指针指向Add函数//进行相关的操作return 0;
}

     


4.库函数实现

 strlen实现:

//参数是const,注意统计的是'\0'之前的字符数量
size_t strlen(const char* str)
{size_t ans = 0;while (*str){ans++;str++;}return ans;
}

 现在我们增加难度,如果我要求不能使用计数器来实现strlen,请写出代码:

//参数是const,注意统计的是'\0'之前的字符数量
size_t strlen(const char* str)
{size_t ans = 0;while (*str){ans++;str++;}return ans;
}

 假如我是面试官,请联系指针特性再写一种方法实现strlen:

size_t strlen(const char* str)
{const char* p=str;while(*p){p++;}return p-str;//指针-指针
}

下面是三个不考的库函数实现:

//1.strcpy实现
char* strcpy(char* dest,const char* src)
{//检查:assert(dest!=null);assert(src!=null);//首先用一个新指针记录dest指针起始位置,便于后面dest后移可以找到头部char* p=dest;while((*dest++=*src++)){}return p;
}//2.strcat实现
char* strcat(char* dest,const char* src)
{//检查:assert(dest!=null);assert(src!=null);//同理记录dest起始位置char* p=dest;//先将dest走空while(*dest!='\0'){dest++;}//再拷贝while((*dest++=*src++)){}return p;
}//3.strcmp实现
int strcmp(const char* str1,const char* str2)
{//判断:assert(str1!=null);assert(str2!=null);while(*str1==*str2){//检查:是否已经出现str1为'\0'情况if(*str1=='\0')   return 0; str1++;str2++;}return *str1-*str2;
}

 对于上面上个库函数的衍生:strncat/strncmp/strncpy

我们是需要保证在n个字符的情况下实现即可!!!

大家可以去参考我之前写的博客:字符串函数详解_tolower 头文件-CSDN博客

下面是几个面试常考的库函数实现:

1.strstr实现:

char* strstr(const char* str1,const char* str2)
{//最简单实现:O(N^2)char* p=(char*) str1;//注意强转//检查str2if(!*str2)return p;while(*p){char* s1=p;char* s2=(char*) str2;while(*s1!='\0'&&*s2!='\0'&&(*s1==*s2)){s1++;s2++;}if(*s2=='\0')return p;p++;}return null;
}


5.内存函数

内存函数:memecpy/memset/memmove/memcmp,其中重点考察的是memmove和memcpy,我们这里只讲解重点内容的实现,其他部分可以参考下面链接:

C语⾔内存函数-CSDN博客

memcpy实现:

//注意点:我们的返回值和参数都是void*,因为我们也不确定要拷贝的类型,num为字节数
void* memcpy(void* dest,const void* src,size_t num)
{void* p=dest;//检查:assert(dest);assert(src);while(num--){*(char*)dest=*(char*)src;dest=(char*)dest+1;src=(char*)src+1;}return p;
}

memmove实现:

//注意:返回值和参数都是void*
void* memmove(void* dest,const void* src,size_t num)
{//检查:assert(dest!=null);assert(src!=null);void* p=dest;//方便返回//判断是否出现内存重叠if(dest<=src||(char*)dest>=(char*)src+num){//无内存重叠while(num--){*(char*)dest=*(char*)src;dest=(char*)dest+1;src=(char*)src+1;}}else{//有内存重叠    //此时我们可以从后向前拷贝dest=(char*)dest+num-1;src=(char*)src+num-1;while(num--){//拷贝*(char*)dest=*(char*)src;dest=(char*)dest-1;src=(char*)src-1;}}return p;
}

memcpy与memmove区别:

如果memmove函数处理的源内存块和目标内存块是可以重叠的,而memcpy是不处理重叠部分的,对于重叠的是未定义的


6.数据储存

整数的储存:

正整数原反补相同,负数各不相同

原码:将整数按照数值位转变成二进制即可,最高位负数为1,正数为0

反码:符号位(最高位)不变,其余为按位取反(负数)

补码:在反码的基础上+1

注意点:在计算机中整数全部按照补码存取

大小端:

        存在原因:对于数据超过一个字节,而内存中一个地址对应一个字节,所以必然产生如何存储顺序的问题。

大端:将数据的低位字节存储在内存地址的高字节中

小端:将数据的高字节存储在在内存地址的低字节中

那么我们如何判断大小端呢?

//通常有以下两种方法
//法一:指针转换法
void Test1()
{int i=1;//0x00000001int ret=*(char*)&i;//将四字节转换为一字节,判断低位是0x00还是0x01if(ret==1){//如果是1,说明数据的小端存储在内存的小端std::cout<<"小端”<<std::endl;}else{//否则说明数据的大端储存在内存的大端std::cout<<"大端"<<std::endl;}
}
//法二:联合体判断法
Union 
{int i;char ch;
}UU;
void Test2()
{UU.i=1;//通过判断ch的值就可以判断大小端,与上面道理相似if(UU.ch==1){std::cout<<"小端”<<std::endl;}else{std::cout<<"大端"<<std::endl;}
}

下面我们来补充一个知识:大小端转换

        这里我们就直接实现:

//现在假设我们要将0x12345678转换为0x78563412template<size_t T>
inline void convert(char* val)
{std::swap(*val,*(val+T-1));convert<T-2>(val+1);
}template<class T>
inline Apply(T* val)
{convert(sizeof(T)>((char*)val);
}int main()
{int i=0x12345678;Apply<int>(&i);std::cout<<i<<std::endl;return 0;
}

最后,感谢大家的支持,祝大家国庆节快乐!!!


http://www.ppmy.cn/devtools/121255.html

相关文章

react+antdMobie实现消息通知页面样式

一、实现效果 二、代码 import React, { useEffect, useState } from react; import style from ./style/index.less; import { CapsuleTabs, Ellipsis, Empty, SearchBar, Tag } from antd-mobile; //消息通知页面 export default function Notification(props) {const [opti…

排序算法之——归并排序,计数排序

文章目录 前言一、归并排序1. 归并排序的思想2. 归并排序时间复杂度及空间复杂度3. 归并排序代码实现1&#xff09;递归版本2&#xff09;非递归版本 二、计数排序1. 计数排序的思想2. 计数排序的时间复杂度及空间复杂度3. 计数排序代码实现 总结&#xff08;排序算法稳定性&am…

【Qt Quick】基础语法:变量类型

在本节中&#xff0c;我们将讨论 QML 中的变量类型。与 C 相似&#xff0c;QML 也有多种变量类型&#xff0c;但在 QML 中&#xff0c;主要分为值类型和对象类型。由于 QML 没有指针的概念&#xff0c;因此在值类型和对象类型的传递中有一些不同点。 值类型和对象类型 值类型…

《深度学习》OpenCV 图像拼接 拼接原理、参数解析、案例实现

目录 一、图像拼接 1、直接看案例 图1与图2展示&#xff1a; 合并完结果&#xff1a; 2、什么是图像拼接 3、图像拼接步骤 1&#xff09;加载图像 2&#xff09;特征点检测与描述 3&#xff09;特征点匹配 4&#xff09;图像配准 5&#xff09;图像变换和拼接 6&am…

HBase 性能优化 详解

HBase 是基于 Hadoop HDFS 之上的分布式 NoSQL 数据库&#xff0c;具有高伸缩性和强大的读写能力。然而&#xff0c;由于其分布式架构和复杂的数据存储模式&#xff0c;在高并发、大规模数据场景下&#xff0c;HBase 性能优化至关重要。从底层原理和源代码层面理解 HBase 的特性…

dockerhub 镜像拉取超时的解决方法

在几个月前&#xff0c;因为一些原因&#xff0c;导致 dockerhub 官网上面的镜像拉取超时&#xff0c;目前可以通过修改仓库地址&#xff0c;通过 daocloud 拉取 public-image-mirror 方式一 源仓库替换仓库cr.l5d.iol5d.m.daocloud.iodocker.elastic.coelastic.m.daocloud.io…

Redis篇(数据类型)

目录 讲解一&#xff1a;简介 讲解二&#xff1a;常用 一、String类型 1. 简介 2. 常见命令 3. Key结构 4. 操作String 5. 实例 二、Hash类型 1. 简介 2. 常见命令 3. 3操作hash 4. 实例 三、List类型 1. 简介 2. 特征 3. 应用场景 4. 常见命令 5. 操作list …

1-仙灵之谜(区块链游戏详情介绍)

1-仙灵之谜&#xff08;区块链游戏详情介绍&#xff09; 前言&#xff08;该游戏仅供娱乐&#xff09;正文 前言&#xff08;该游戏仅供娱乐&#xff09; 依稀记得本科那会儿参加了一个区块链实验室&#xff0c;那时每周末大家都会爬山或者抽出一下午讨论区块链以及未来&#x…