C++学习征途一

2018-09-30  本文已影响0人  Eden0503

Q1:一个实际结果超出unsigned char 的表示范围,编译器会怎么处理呢?

A1:编译器会一刀切,比如,下例中编译器先将a转换为int类型,但是此时 超出了unsigned char 的表示范围,最终的输出是 ‘Y’,因为345-256 = 89 ASCII码为89对应的是字符 ‘Y’。超过范围的对最大范围上限取模。 即345 mod 256 。

#include<iostream>
using namespace std;
int main() {
    unsigned char a = 345;
    cout << a << endl;  //   345-256 = 89   ‘Y’
    return 0;
}

Q2:查看以下程序的差别。

#include<iostream>
using namespace std;

int main() {
    float a = 1.0;
    cout << "(int)a: "<<(int)a << endl;
    cout <<"&a: "<< &a << endl;
    cout << "(int&)a: "<<(int&)a << endl;

    float b = 0.0;
    cout << "(int)b: "<<(int)b << endl;
    cout << "&b: "<< &b << endl;
    cout << "(int&)b: "<<(int&)b << endl;
    system("pause");
    return 0;
}

结果是:


image.png

Q3:C++中几种进制怎么输出?

A3:八进制、十进制、十六进制都可以直接通过在cout语句中加上 oct dec hex来直接转换。(cout默认输出是十进制),二进制就需要用到bitset 了。

#include<iostream>
#include<bitset>
using namespace std;

int main() {
    int a = 256;
    cout << "十进制"<< a << endl;
    cout << "八进制"<< oct << a << endl;
    cout << "十六进制" << hex << a << endl;
    cout << "十进制(重新回)" << dec << a << endl;

    // 要想输入二进制,可以用bitset<size_t N>进行转换输出
    bitset<sizeof(int) * 8> bin_a(a);
    cout << "二进制" << bin_a << endl;
    system("pause");
    return 0;
}

上述程序运行结果为:


image.png

Q4:判断一个数X是不是2^N次方。

A4:用 X&(X-1) 来判断,结果为0,就是。

#include<iostream>
#include<bitset>
using namespace std;

// 程序是为了说明要想判断一个数X是不是2^n, 只要判断 X & (X-1) 是不是为0 即可
int main() {
    int a = 256;
    // 要想输入二进制,可以用bitset<size_t N>进行转换输出
    bitset<sizeof(int) * 8> bin_a(a);    // 相当于 将 a的二进制表示赋值给 bin_a
    cout << "二进制" << bin_a << endl;
    bitset<sizeof(int) * 8> bin_aa(a&(a - 1));  // 相当于 将 a&(a-1)的二进制表示赋值给 bin_a
    cout << "二进制" << bin_aa << endl;
    system("pause");
    return 0;
}

上述程序运行结果为:


image.png

Q5:判断一个数X的二进制中1的个数。

A5:利用 X&(X-1).

#include<iostream>
#include<bitset>
using namespace std;

int main() {
    int X = 5678;
    int count = 0;
    while (X) {
        count++;
        X = X & (X - 1);
    }
    cout << "X二进制表示中1的个数:" << count << endl;

    int _X = 5678;
    bitset<sizeof(int) * 8> bin_X(_X);    // 相当于 将 _X 的二进制表示赋值给 bin_X
    cout << "_X的二进制表示:" << bin_X << endl;
    system("pause");
    return 0;
}

Q6:数据类型不统一,占用内存产生的对齐原则。空类占用1

#include<iostream>
#include<bitset>
using namespace std;
class A{
    int a; // int占4个字节
    float b; // float 占4个字节
    char c; // char占4个字节,根据对齐原则
    int array[3];  // int array 占12个字节 3*4
};

class B {
};

int main() {
    cout<< sizeof(A) <<endl; // 类A占用结果是24
    cout << sizeof(B) << endl; // 空类B 占用结果是1
    return 0;
}

Q7:给固定内存地址赋值为value。

A7:在尝试的时候需要注意一下,并不是所有的内存地址都可以存入数据的,可以先用 int i= 0;中i的&i来做实验。以下实现的是在给定的内存地址“0x010FFBB0”赋值为0x100.

#include<iostream>
using namespace std;

int main(){
    int i = 0;
    cout<< &i <<endl; // 输出 010FFBB0
    int *p = (int *)0x010FFBB0;   // 必须有一个类型强制转换
    *p = 0x100;
    cout << *p << endl; // 输出是十进制的Ox100,即256
    return 0;
}

注意:如果内存为“0x123456789”, 超界了,此时要用 (long*)0x123456789 来实现强制类型转换。

Q8:char *ch 和 char ch[]的区别;

A8:char ch[]分配的是一个局部数组,是可以修改的。

int main(){
    char ch1[] = "hello";
    const char *ch2 = "hello";  // *ch其实是分配一个全局数组,不可以修改,因此在前必须加上const.
    return 0;
}

Q9:函数指针,函数返回指针,const指针,指向const的指针,指向const的const指针。

函数指针(指向函数的指针): void(*f)()
函数返回指针:void* f()
const指针:const int*
指向const的指针:int* const
指向const的const指针:const int* const

Q10:数组指针和指针数组。

1. 数组指针(行指针),定义 int (*p)[N];  表示的是p是一个指针,指向一个整型的一维数组,该数组的长度是N,若执行 p+1, p将会跨过N个整型数据的长度。
在数组指针中,()的优先级高。
int(*a)[10] : a是一个数组指针,指向一个含有10个int元素的数组。
-------------------------------------example:-----------------------------
int main(){
    int v[2][3] = { {1,2,3},{4,5,6} };
    cout << v[0] << endl;  // Ox0135FB34
    cout << v[1] << endl;  // Ox0135FB40

    int(*p)[3] = v;
    p = v;  
    cout << p[0] << endl;  // Ox0135FB34
    cout << p[0][0] << endl;  // 1
    cout << p[0][1] << endl;  // 2
    cout << p[0][2] << endl;  // 3

    p++;  // 执行该语句之后,p=p+1; p跨过行 v[0][] 直接指向了 v[1][].
    cout << p[0] << endl;  // Ox0135FB40
    cout << p[0][0] << endl;  // 4
    cout << p[0][1] << endl;  // 5
    cout << p[0][2] << endl;  // 6
    return 0;
}
-------------------------------------example:-----------------------------
2. 指针数组,定义 int *p[N];  [ ] 先和p结合成一个数组,而 int * 说明这是一个整型指针数组,其中有N个指针类型的数组元素。指针数组指的是一个数组里面装的是指针。
执行p+1是错误的 ;
执行p=a是错误的, 因为p是个不可知的表示。
只存在p[0]、p[1]、p[2]...p[n-1],而且它们分别是指针变量可以用来存放变量地址。
*p=a是正确的,这里*p表示指针数组第一个元素的值,a的首地址的值。
在指针数组, [ ] 的优先级高。
int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2]。
总结:
数组指针只是一个指针变量,似乎是C语言里专门用来指向二维数组的,它占有内存中一个指针的存储空间。指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。
拓展:
比如要表示数组中i行j列一个元素:
*(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j]   都是正确的。

Q11: C++中的迭代器 iterator 怎么使用?

#include<iostream>
#include<vector>
using namespace std;

int main(){
    vector<int > array = { 1,2,3,4,5,6 };
    vector<int >::iterator itor;
    for (itor = array.begin(); itor != array.end();itor++) {   // itor需要自增,才可以依次获取vector中的数值
        cout << *itor << endl;   // 注意itor其实相当于一个指针
    }
    return 0;
}

Q12: C++是面向对象的语言,面向对象的特征有啥?

A12: 封装、继承、多态。 三个特征。

1. 封装
隐藏对象的内部细节,代码模块化;对外界形成一个边界;只保留有限的对外接口;使用方便,安全性好。
2. 继承
使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行改造、扩展。
通过继承创建的新类称为“子类”或“派生类”。
被继承的类称为“基类”、“父类”或“超类”。
3. 多态
同样的消息作用再不同对象上可能引起不同的行为。(打篮球、乒乓球都是大打,但是是不同方式来进行的。)
实现多态的两种方式:  覆盖 和 重载
覆盖:子类重新定义父类的虚函数的做法,即派生类重写基类的虚函数。
重载:允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。功能不同的函数就不要写成重载了。
参数类型不同:
int add(int x, int y)
float add(float x, float y)
参数个数不同:
int add(int x, int y)
int add(int x, int y, int z)

Q13: C++中显示类型转换有什么?

A13:C++引入了4个新的强制类型转换操作符,static_cast、dynamic_cast、const_cast、reinterpret_cast,用以支持更为精细的类型转换。(只要知道就行,必要时查资料)
使用时的规范是: 类型转换操作符<类型说明符>(表达式)

-------------------------------------example:-----------------------------
将Z变量类型转成 int 类型:
int(Z)    (int)Z     static_cast<int> (Z)     这三种可以,C++中推荐使用最后一种static_cast<int> (Z)
-------------------------------------example:-----------------------------

Q14: C++中如何控制输出精度?

A14: 有两种做法:一、使用count输出。 二、使用printf.

-------------------------------------example:-----------------------------
要求: 输出保留两位小数
1 使用cout输出。
cout是C++的标准输出流,在iomanip头文件中有对其进行格式操作的函数。
其中setiosflags(ios::fixed)可以设置以浮点数形式输出,setprecision函数可以设置精度。
#include<iostream>
#include<iomanip>  // 配合的头文件
using namespace std;
int main()
{
    float v  = 1.54321;
    cout << setiosflags(ios::fixed);//设置输入浮点形式
    cout.precision(2);   //设置两位有效数字
    cout  << v  << endl; //输出并换行  输出结果1.54
    return 0;
}

2 使用printf。
C++完整兼容C语言,所以同样可以使用C的输出函数printf。
在输出精度控制上C的printf更为简单,但需要根据数据类型调整输出格式字符。
对于float可以用%.2f, 而double则需要用%.2lf。
以float为例,代码如下:
#include<iostream>
#include<cstdio>//printf所在头文件
using namespace std;
int main()
{
    float v = 1.54321;
    printf("%.2f\n",v);  // 输出结果1.54
    return 0;
}

Q15:创建一个二维的vector,大小为 m*n, 数组名为 ivec,并且初始化。

A15:vector<vector<int > > ivec(m, vector<int >(n,0));

vector<vector<int > > ivec(m, vector<int >(n));   // 这样其实已经创建好了,但是没有初始化。
vector<vector<int > > ivec(m, vector<int >(n,0));  // 不仅创建了一个m*n的vector,而且全部初始化为0
上一篇 下一篇

猜你喜欢

热点阅读