C/C++|C/C++ basis 02

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; }

    推荐阅读