1.写出程序打印结果
#include
int main(void)
{
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);
printf("%d,%d\n",*(a+1),*(ptr-1));
return 0;
}
程序结果2,5,原因:数组名a可以做数组的首地址,而&a是数组的指针
(即(&a+1)是由a[0][m]移动到a[1][m],此例中m为5)
2.编码实现变量某位清0或置1 (位逻辑操作)
注:移位操作指对某变量的二进制进行移位,无论该变量是何种进制格式表示的。
eg:
#define BIT3(0x1<<3)
int a;
a|=BIT3;
//将a的第三位置1
a&=~BIT3;
//将a的第三位置0
3.不用临时变量对a,b的值交换
方法一:
a=a+b;
b=a-b;
a=a-b;
方法二:
a^=b;
b^=a;
a^=b;
4. string 原理及实现
#pragma once
#include
class String{
private:
char*data;
//字符串内容
size_t length;
//字符串长度
public:
String(const char* str = nullptr);
//通用构造函数
String(const String& str);
//拷贝构造函数
~String();
//析构函数
String operator+(const String &str) const;
//重载+
String& operator=(const String &str);
//重载=
String& operator+=(const String &str);
//重载+=
bool operator==(const String &str) const;
//重载==
friend std::istream& operator>>(std::istream &is, String &str);
//重载>>
friend std::ostream& operator<<(std::ostream &os, String &str);
//重载<<
char& operator[](int n)const;
//重载[]
size_t size() const;
//获取长度
const char* c_str() const;
//获取C字符串
};
#include"String.h"
//通用构造函数
String::String(const char *str){
if (!str){
length = 0;
data = https://www.it610.com/article/new char[1];
//一定要用new分配内存,否则就变成了浅拷贝;
*data ='\0';
}else{
length = strlen(str);
//
data = https://www.it610.com/article/new char[length + 1];
strcpy(data,str);
}
}
//拷贝构造函数
String::String(const String& str){
length = str.size();
data = new char[length + 1];
//一定要用new,否则变成了浅拷贝
strcpy(data,str.c_str());
}
String::~String(){
delete[]data;
length = 0;
}
//重载+
String String::operator+(const String &str) const{
String StringNew;
StringNew.length = length + str.size();
StringNew = new char[length + 1];
strcpy(StringNew.data, data);
//字符串拼接函数,即将str内容复制到StringNew内容后面
strcat(StringNew.data, str.data);
return StringNew;
}
//重载=
String& String::operator=(const String &str){
if (this == &str){
return *this;
}
delete []data;
//释放内存
length = str.length;
data = new char[length + 1];
strcpy(data,str.c_str());
return *this;
}
//重载+=
String& String::operator+=(const String &str){
length += str.size();
char *dataNew = new char[length + 1];
strcpy(dataNew, data);
delete[]data;
strcat(dataNew, str.c_str());
data = dataNew;
return *this;
}
//重载==
bool String::operator==(const String &str) const {
if (length != str.length){
return false;
}
return strcmp(data, str.data) ? false : true;
}
//重载[]
char& String::operator[](int n) const//str[n]表示第n+1个元素
{
if (n>= length){
return data[length - 1];
//错误处理
}else{
return data[n];
}
}
//获取长度
size_t String::size() const {
return this->length;
}
//获取C字符串
const char* String::c_str() const{
return data;
}
//重载>>
std::istream& operator>>(std::istream &is, String &str){
char tem[1000];
is >> tem;
str.length = strlen(tem);
str.data = https://www.it610.com/article/new char[str.length + 1];
strcpy(str.data, tem);
return is;
}
//重载<<
std::ostream& operator<<(std::ostream &os, String &str){
os << str.c_str();
return os;
}
关于operator>>和operator<<运算符重载,我们是设计成友元函数(非成员函数),
并没有设计成成员函数,原因如下:
对于一般的运算符重载都设计为类的成员函数,而>>和<<却不这样设计,
因为作为一个成员函数,其左侧操作数必须是隶属同一个类之下的对象,
如果设计成员函数,输出为对象>>cout >> endl;
(Essential C++)不符合习惯。一般情况下:
将双目运算符重载为友元函数,这样就可以使用交换律,比较方便
单目运算符一般重载为成员函数,因为直接对类对象本身进行操作
运算符重载函数可以作为成员函数,友元函数,普通函数。普通函数:一般不用,通过类的公共接口间接访问私有成员。
成员函数:可通过this指针访问本类的成员,可以少写一个参数,
但是表达式左边的第一个参数必须是类对象,通过该类对象来调用成员函数。
友元函数:左边一般不是对象。<< >>运算符一般都要申明为友元重载函数
5.编码辨别系统是16位或32位,大端或小端模式
32位处理器一次只能处理32位,也就是4个字节的数据,虚拟地址空间的最大值是4G。
64位处理器一次能处理64位,也就是8个字节的数据,虚拟地址空间的最大值是16T。32位处理器:系统指针(32位 ),long(32位),int(32位),short(16位)
64位处理器:系统指针(64位 ),long(64位),int(32位),short(16位)(1)辨别系统是16位或32位
方法一:
sizeof(指针)。结果为2、4、8时系统分别对应16、32、64位。方法二:
int i=65536,j=65535;
cout<65536){
cout<<" 32 bit"<
6. 设计一个只能在堆上或栈上实例化的类
只能在堆上实例化的类:将析构函数定义为private,在栈上不能自动调用析构函数,
只能手动调用,也可将构造函数定义为private但需要手动写个函数实现独享的构造。
class CHeapOnly//只能在堆上实例化的类
{
public:
CHeapOnly(){
cout<<"Constructor of CHeapOnly!"<
7. C库函数的实现
memcpy:
void *memcpy(void *dest, const void *src, size_t count) {
char *tmp = dest;
const char *s = src;
while (count--){
*tmp++ = *s++;
}
return dest;
}
strcpy:
char *strcpy(char *dst,const char *src) {
assert(dst != NULL && src != NULL);
char *ret = dst;
while((* dst++ = * src++) != '\0') ;
return ret;
}
strcat:
char *strcat(char *strDes, const char *strSrc){
assert((strDes != NULL) && (strSrc != NULL));
char *address = strDes;
while (*strDes != ‘\0′){
++ strDes;
}
while ((*strDes ++ = *strSrc ++) != ‘\0′)
return address;
}
strncat:
char *strncat(char *strDes, const char *strSrc, int count){
assert((strDes != NULL) && (strSrc != NULL));
char *address = strDes;
while (*strDes != ‘\0′){
++ strDes;
}
while (count -- && *strSrc != ‘\0′ ){
*strDes ++ = *strSrc ++;
}
*strDes = ‘\0′;
return address;
}
strcmp:
int strcmp(const char *str1,const char *str2){
/*不可用while(*str1++==*str2++)来比较,当不相等时仍会执行一次++,
return返回的比较值实际上是下一个字符。应将++放到循环体中进行。*/
while(*str1 == *str2){
if(*str1 == '\0')
return0;
++str1;
++str2;
}
return *str1 - *str2;
}
strncmp:
int strncmp(const char *s, const char *t, int count){
assert((s != NULL) && (t != NULL));
while (*s && *t && *s == *t && count --) {
++ s;
++ t;
}
return (*s – *t);
}
strlen:
int strlen(const char *str){
assert(str != NULL);
int len = 0;
while (*str ++ != ‘\0′)
++ len;
return len;
}
strpbrk:
char * strpbrk(const char * cs,const char * ct){
const char *sc1,*sc2;
for( sc1 = cs;
*sc1 != '\0';
++sc1){
for( sc2 = ct;
*sc2 != '\0';
++sc2){
if (*sc1 == *sc2){
return (char *) sc1;
}
}
}
return NULL;
}
strstr:
char *strstr(const char *s1,const char *s2){
int len2;
if(!(len2=strlen(s2)))
//此种情况下s2不能指向空,否则strlen无法测出长度,这条语句错误
return(char*)s1;
for(;
*s1;
++s1){
if(*s1==*s2 && strncmp(s1,s2,len2)==0)
return(char*)s1;
}
return NULL;
}
推荐阅读
- c/c++|有感 Visual Studio 2015 RTM 简介 - 八年后回归 Dot Net,终于迎来了 Mvc 时代,盼走了 Web 窗体时代...
- Qt实战|Qt+OpenCV联合开发(二十一)--图像翻转与旋转
- Qt实战|Qt+OpenCV联合开发(十四)--图像感兴趣区域(ROI)的提取
- Qt实战|Qt+OpenCV联合开发(十三)--通道分离与合并
- opencv|Qt+OpenCV联合开发(十六)--图像几何形状绘制
- Qt实战|Qt+OpenCV联合开发(十七)--随机数与随机颜色
- SNAT的MASQUERADE地址选择与端口选择
- IPTABLES的连接跟踪与NAT分析
- IPVS分析