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 = new char[1];  //一定要用new分配内存,否则就变成了浅拷贝;
        *data = '\0';
    }else{
        length = strlen(str); //
        data = 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 = 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"< 
int main()
{
    #ifdef __x86_64__
        printf("__x86_64__\n");
    #elif __i386__    
        printf("__i386__\n");
    #endif
    return 0;
}

(2)判断大端模式或小端模式
大端模式:字数据的高字节存储在低地址中,字数据的低字节存放在高地址中。
小端模式:.................高.........................低.....。

方法一:直接判断内存存储情况
int isLittleEndian(void)
{
int i=0x12345678;
char *c=(char *)&i;
return ((c[0] == 0x78) && (c[1] == 0x56) && (c[2] == 0x34) && (c[3] == 0x12));
}

方法二:用union判断
typedef union {
    int i;
    char c;
} myUnion;
// 1: Little Endian; 0: Big Endian.
int isLittleEndian02(void)
{
    myUnion u;
    u.i = 1;
    return (u.i == u.c);
}
读取成员c就相当于读取成员a的低位的第一个字节值(联合体union的存放顺序是所有成员都从低地址开始存放)。
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++ basis 02)