一、C++第一个项目
入门技巧
- 1.使用解决方案资源管理器窗口添加/管理文件
- 2.使用团队资源管理器窗口连接到源代码管理
- 3.使用输出窗口查看生成输出和其他消息
- 4.使用错误列表窗口查看错误
- 5.转到"项目"-->"添加新项"以创建新的代码文件 或者转到"项目"-->"添加现有项"添加到项目中
- 6.将来若要再次打开此项目,选择.sIn文件
代码:
#include <iostream> //包含的头文件 using namespace std; //缺省指定的命名空间 int main() //程序入口 程序执行的入口 每个程序有且仅有一个main函数 { //<< 输出运算符 //cout 向控制台输出内容的指令 // ; C++语句结束符 cout << "HelloWorld!" << endl; return 0; }
二、C++输出数据
数据是信息的载体,写程序的目的就是为了处理数据
1.数据的分类
数据有数字、字符和字符串三种类型
数字:直接书写,如100、89、23;
字符:用半角的单引号包含的一个符号,如:'A'、'z'、'0'、‘9’ 、‘~’、‘+’等;
字符串:用半角的双引号包含的多个符号,如:"Hello World";
2.输出数据
std::cout 可以输出各种类型的数据;
<<操作符可以拼接多个数据项;
std::eddl 也可以用于换行;
using namespace std;制定缺省的命名空间
3.示例代码
#include <iostream> using namespace std; int main() { //用于多个数据项的输出: 姓名、年龄、性别、学号、专业 cout << "姓名" << "C++初学者" << endl << "年龄:" << 25 << endl << "性别:" << "男" << endl << "学号:" << 20990164 << endl << "专业:" << "计算机科学与技术" << endl; return 0; }
解决VS编译中文报错 error C2001:常量中有换行符
产生原因:文件中有中文字符,但是文件是utf-8格式的,使用msvc编译器编译时就会产生上述错误
解决办法:
方式1(不推荐试了没用):
通过在项目里设置编译选项,/utf-8
项目->右键属性->C/C++ -> 命令行,在下方输入框添加 /utf-8,就会在编译时采用utf-8编码来编译
方式3:(亲测可用已解决,但是这种方法会使原有项目在使用vs打开时出现中文乱码)
打开控制面板-->找到时钟和区域
找到区域
点击管理-->更改系统区域设置
勾选上Beta-->重启电脑
三、指针的基本概念
1、变量的地址
变量是内存变量的简称,在C++中,每定义一个变量,系统就会给变量分配一块内存,内存是有地址的。
c++中使用运算符&获取变量在内存中的起始地址。
2指针变量
指针变量简称指针,它是一种特殊的变量,专门用于存放变量在内存中的起始地址。
语法:数据类型*变量名;
数据类型必须是合法的C++数据类型
#include <iostream> using namespace std; int main() { int a; char b; bool c; string d; //int* pa = &a; //让指针pa指向变量a //char* pb = &b; //r让指针pb指向变量b //bool* pc = &c; //string* pd = &d; int* pa; //定义指针pa char* pb; bool* pc; string* pd; a = 1; /*cout << "变量a的地址是:" << (long long)&a << endl; cout << "变量b的地址是:" << (long long)&b << endl; cout << "变量c的地址是:" << (long long)&c << endl; cout << "变量d的地址是:" << (long long)&d << endl; cout << endl; cout << "指针变量a的地址是:" << (long long)pa << endl; cout << "指针变量b的地址是:" << (long long)pb << endl; cout << "指针变量c的地址是:" << (long long)pc << endl; cout << "指针变量d的地址是:" << (long long)pd << endl; cout << endl; cout << sizeof(pa) << endl; cout << sizeof(pb) << endl; cout << sizeof(pc) << endl; cout << sizeof(pd) << endl; return 0;*/ }
3.使用指针
声明指针变量后,在没有赋值之前, 里面是乱七八糟的值, 这时候不能使用指针。
指针存放变量的地址,因此,指针名表示的是地址(就像变量名可以表示变量的值一样)
*运算符被称为间接值或解除引用(解引用) 运算符,将它用于指针,可以得到该地址的内存中存储
的值, *也是乘法符号, C++根据上下文来确定所指的是乘法还是解引用#include<iostream> using namespace std; int main() { //定义一个变量 int a; //初始化变量 a = 3; //定义一个指针 int* p = &a; //输出a的值 cout << "a=" << a << endl; cout << "*p=" << *p << endl; //对指针p解引用并且赋值 *p = 8; cout << "a=" << a << endl; cout << "*p=" << *p << endl; }
4.指针用于函数的参数
如果把函数的形参声明为指针,调用的时候把参数的地址传进去,形参中存放的是实参的地址,在函数中通过解引用的方法直接操作内存中的数据,可以修改实参的值,这种方法称为地址传递或者传地址
传地址的意义:可以在函数中修改实参的值.减少内存拷贝,提升性能
#include <iostream> using namespace std; //函数声明 void func(int num, string str); int main() { int bh = 3; string message = "峡谷掉分王"; //函数调用 func(bh, message); /*下边代码模拟函数调用的过程,等同于func(bh,message); *{ int num = bh; string str = message; cout << "亲爱的" << num << "号:" << str << endl; }*/ } //函数定义 void func(int num, string str) { cout << "王者荣耀" << num << "号:" << str << endl; }
值传递:在代码中修改形参的不会改变实参的值
四、用const修饰指针
1、常量指针
语法:const 数据类型 *变量名
不能通过解引用的方法修改内存地址中的值(用原始的变量名是可以修改的)
#include <iostream> using namespace std; int main() { //定义普通变量 语法:数据类型 变量名; int a = 3; int b = 8; //定义常量指针 语法:const 数据类型 *变量名 const int* p = &a; //使用取地址符&将普通变量a的值复制给常量指针p cout << "a=" << a << endl; //输出结果 3 cout << "*p=" << *p << endl; //输出结果 3 }
输出结果
通过解引用修改常量指针的值
#include <iostream> using namespace std; int main() { //定义普通变量 语法:数据类型 变量名; int a = 3; int b = 8; //定义常量指针 语法:const 数据类型 *变量名 const int* p = &a; //使用取地址符&将普通变量a的值复制给常量指针p //修改常量指针的值 *p = 13; //这种方式是通过解引用的方法修改内存地址中的值 报错 cout << "a=" << a << endl; //输出结果 3 cout << "*p=" << *p << endl; //输出结果 3 }
运行报错
用原始变量名可以修改
#include <iostream> using namespace std; int main() { //定义普通变量 语法:数据类型 变量名; int a = 3; int b = 8; //定义常量指针 语法:const 数据类型 *变量名 const int* p = &a; //使用取地址符&将普通变量a的值复制给常量指针p //修改常量指针的值 //*p = 13; //这种方式是通过解引用的方法修改内存地址中的值 //用原始变量名修改内存地址中的值(可以修改) a = 13; cout << "a=" << a << endl; //输出结果 3 cout << "*p=" << *p << endl; //输出结果 3 }
运行结果(可以修改成功)
指向变量(对象可以改变)(之前是指向变量a的 后来可以改为指向变量b)
#include <iostream> using namespace std; int main() { //定义普通变量 语法:数据类型 变量名; int a = 3; int b = 8; //定义常量指针 语法:const 数据类型 *变量名 const int* p = &a; //使用取地址符&将普通变量a的值复制给常量指针p //修改常量指针的值 //*p = 13; //这种方式是通过解引用的方法修改内存地址中的值 //用原始变量名修改内存地址中的值(可以修改) a = 13; cout << "a=" << a << endl; //输出结果 3 cout << "*p=" << *p << endl; //输出结果 3 //原本是指向a修改后指向b p = &b; cout << "b=" << endl; cout << "p=" << *p << endl; }
常量指针的应用场景
一般用于修饰函数的参数,表示不希望在函数里修改内存地址的值
2、指针常量
语法: 数据类型 *const 变量名
指向的变(对象)不可以改变,在定义的同时必须初始化;可以通过解引用的方法修改内存地址中的值
在定义的同时必须初始化(没有初始值会报错)
在定义的时候赋初始值
指向变量不可以改变(之前是指向变量a 不可以再指向变量b)
#include <iostream> using namespace std; int main() { int a = 3; int b = 8; int* const p = &a; //使用解引用的方法去修改内存地址中的值 *p = 13; cout << "a=" << a << endl; cout << "*p=" << *p << endl; //之前指向a,现在将指针常量指向b 不可以改变 p = &b;//报错 }
3、常指针常量
语法: const 数据类型 *const 变量名;
指向变量(对象)不可以改变 不能通过解引用的方法修改内存地址中的值
4、常量指针、指针常量、常指针常量
常量指针:原先常量指针的指向原始变量a,可以通过修改 原始变量a的值来修改常量指针的值,但是不能通过修修改指针变量的值来修改原始变量的值;并且常量指针可以有原先指向变量a改为转向变量b;
//定义普通变量 语法:数据类型 变量名; int a = 3; int b = 8; //定义常量指针 语法:const 数据类型 *变量名 const int* p = &a; //使用取地址符&将普通变量a的值复制给常量指针p //修改常量指针的值 //*p = 13; //这种方式是通过解引用的方法修改内存地址中的值 报错 //用原始变量名修改内存地址中的值(可以修改) a = 13; cout << "a=" << a << endl; //输出结果 3 cout << "*p=" << *p << endl; //输出结果 3 //原本是指向a 可以指向b p = &b; cout << "b=" << b << endl; cout << "p=" << *p << endl;
指针常量:原先指针常量指向原始变量a,可以通过修改常量指针的值来修改原始变量a的值,并且指针常量不可以由原先指向变量a改为转向变量b;
常指针常量:指针指向不可以改,指针指向的值也不可以该(原先指针常量指向原始变量a,不可以通过修改常量指针的值来修改原始变量a的值,不可以由原先指向变量a改为转向变量b;)
5、void关键字
在C++中,void 表示无类型,主要三个用途:
函数的返回值用void,表示函数没有返回值。
void func(int ,int b) { //函数体代码 return; }
函数的参数填void,表示函数不需要参数或者让参数列表空着
int fun(void) { //函数体代码 }
函数的参数用void*,表示接受任意数据类型的指针
注意:
不能用void声明变量,他不能代表一个真实的变量
不能对void*指针解引用(需要转换成其他类型的指针)
把其它类型的指针赋值给void*指针不需要转换
解引用的时候需要知道书局占用内存空间的大小
没有使用void*的时候会出现"烫烫烫烫烫"
使用void*解决上边问题
另一种方法: 写一个函数来实现:函数有两个形参:一个变量名,另外一个存地址,不需要返回值
#include <iostream> using namespace std; //声明函数 void func(string varname, int* p); //如果将int*型指针改为void*指针不需要在调用函数是进行强制转换 int main() { //显示变量十六进制地址 int a; char b; cout << "a的地址是:" << &a << endl; cout << "b的地址是:" << &b << endl; //函数调用 func("a", &a); //func("b", &b);//报错 不能将字符指针转换成整形指针 func("b", (int*)&b); //需要将字符指针转换成整形指针 /*cout << "a的地址是:" << (void*)&a << endl; cout << "b的地址是:" << (void*)&b << endl;*/ } //函数定义 void func(string varname, int* p) { cout << varname << "地址是:" << p << endl; }
6、C++内存模型
内存空间:从地址从低到高:代码段(存放程序中的二进制代码)、数据段(存放全局变量、静态变量)、堆(由程序员管理,需要手动 new malloc delete free 进行分配和回收,空间较大,可能会出现内存泄漏和空闲碎片的情况、堆是向上增长)、栈(由编译器管理分配和回收,存放局部变量和函数参数、栈是向下增长)
栈和堆的区别:
1、管理方式不同:栈是需要系统管理分配和回收;堆则需要程序员手动new malloc delete free 分配和回收
2、空间大小不同:堆内存空间大小受限于物理内存空间(内存越大,分配的空间就越多);而栈的就特别小,一般只有8M(修改系统参数可以修改栈的大小)
3、分配方式不同:堆是动态分配;栈有动态分配和静态分配
4、分配效率不同:栈是系统提供的数据结构,计算机在底层提供了对栈的支持,进栈和出栈有专门指令,效率比较;堆是由C++函数库提供
7、动态分配内存 new 和 delete
//动态分配内存的步骤
//1.声明一个指针
// 2.用new运算符想系统申请一块内存,让指针指向这块内存
// 3.通过指针解引用方法,像使用变量一样使用这块内存
// 4.如果这块内存不用了,用delete运算符释放这块内存
// 申请内存的语法:new 数据类型(初始值) // c++11
// 释放内存语法:delete 地址;#include <iostream> //包含头文件 using namespace std; //指定缺省的命名空间 int main() //程序的入口 { //动态分配内存的步骤 //1.声明一个指针 int* p; // 2.用new运算符想系统申请一块内存,让指针指向这块内存 p = new int(5); // 3.通过指针解引用方法,像使用变量一样使用这块内存 cout << "*p=" << *p << endl; *p = 8; //解引用 cout << "*p=" << *p << endl; // 4.如果这块内存不用了,用delete运算符释放这块内存 delete p; // 申请内存的语法:new 数据类型(初始值) // c++11 // 释放内存语法:delete 地址; return 0; }
注意:
1、如果动态分配内存不用了,必须要用delete释放,否则有可能用尽系统的内存;
2、动态分配的内存生命周期与程序相同,程序退出时,如果没有释放,系统将自动回收
8、二级指针
指针是指针变量的简称,也是变量,是变量就有地址
指针用于存放普通变量的地址
二级指针用于存放指针变量的地址
声明二级指针的语法:数据类型** 指针名;
使用指针有两个目的:(1)传递地址;(2)存放动态分配的内存地址。
在函数中,如果传递普通变量的地址,形参用指针;传递指针的地址的地址,形参用二级指针;
#include <iostream> //包含头文件 using namespace std; //指定缺省的命名空间 int main() { //先声明一个普通变量i; int i; //变量初始化赋值为8 i = 8; //显示这个变量的值和地址 cout << "i的值=" << i << endl; cout << "i的地址是:" << &i << endl; cout << endl; //在声明一个指针pi,让它指向变量i int* pi = &i; cout << "pi的值=" << pi << endl; cout << "pi的地址是:" << &pi << endl; //解引用的结果 cout << "*pi的值=" << *pi << endl; cout << endl; //声明二级指针 int** ppi = π cout << "ppi的值=" << ppi << endl; cout << "ppi的地址是:" << &ppi << endl; cout << "*ppi的值=" << *ppi << endl; cout << endl; cout << "**pi的值=" << **ppi << endl; }
9.空指针
在C和C++中,用0或者NULL都可以表示空指针
声明指针后,在赋值之前,让它指向空,表示没有指向任何地址.
1、使用空指针的后果
如果对空指针解引用,程序会崩溃。
如果对空指针使用delete运算符,系统将忽略该操作,不会出现异常。所以内存释放后,也应该把指针指向空。
使用空指针方式定义函数就会导致程序蹦崩溃
#include <iostream> //包含头文件 using namespace std; //指定缺省的命名空间 //函数声明 void func(int* no, string* str); int main() { ////声明编号 //int bh = 3; ////声明信息 //string message = "我是C++程序员"; ////函数调用 //func(&bh, &message); /**使用指针方式**/ //使用空指针声明编号 int* bh = 0; /*new int(3);*/ //使用空指针声明信息 string* message = 0; /*new string("杭州智诺科技");*/ //函数调用 func(bh, message); //释放内存 delete bh; delete message; } //函数定义 void func(int* no, string* str) { cout << "你好" << *str << "我是" << *no << "号" << "韦广豪" << endl; //程序崩溃的原因:因为使用空指针,解引用就成了非法操作 }
问题解决方法:在定义函数中增加判断代码,如果形参是空指针,就返回不要继续执行下面的流程
#include <iostream> //包含头文件 using namespace std; //指定缺省的命名空间 //函数声明 void func(int* no, string* str); int main() { ////声明编号 //int bh = 3; ////声明信息 //string message = "我是C++程序员"; ////函数调用 //func(&bh, &message); /**使用指针方式**/ //使用空指针声明编号 int* bh = 0; /*new int(3);*/ //使用空指针声明信息 string* message = 0; /*new string("杭州智诺科技");*/ //函数调用 func(bh, message); //释放内存 delete bh; delete message; } //函数定义 void func(int* no, string* str) { //判断形参是否为空指针的代码 if ((no==0) || (str==0)) { return; } //目的:保证代码的健壮性 cout << "你好" << *str << "我是" << *no << "号" << "韦广豪" << endl; }
解决程序崩溃问题,但是没有显示任何内容;
C++11的 nullptr
C++11建议使用nullptr表示空指针,也就是(void*)0
10.野指针
野指针:就是指针指向的不是一个有效的地址;
报错原因:不能将十六进制数转换为指针
解决办法:强制类型转换(但是会地址显示没问题,但是解引用失败 程序崩溃)
在程序中,如果访问野指针,可能会造成程序崩溃
出现野指针的情况主要有三种:
1、指针在定义的时候,如果没有进行初始化,它的值是不确定的
(也就是说指针在没有初始化之前编译器不让使用该指针)
2、如果用指针指向了动态分配的内存,内存被释放后,指针不会置空,但是指向地址已失效
#include <iostream> //包含的头文件 using namespace std; //指定缺省的命名空间 int main() { //声明一个指针并分配一块内存空间 int* p; p = new int(3); //显示指针值和对p解引用的结果 cout << "p=" << p << endl; cout << "*p=" << *p << endl; delete p; cout << "p=" << p << endl; cout << "*p=" << *p << endl; }
(解释:释放内存,程序崩溃)
3、指针指向的变量已超越变量的作用域(变量的内存空间已被系统回收)
#include <iostream> //包含的头文件 using namespace std; //指定缺省的命名空间 //声明函数 int* func(); int main() { //声明一个指针 int* p; //函数调用 func(); //将函数func复制给指针p p = func(); //相当于 int*p=func(); //显示指针值和对p解引用的结果 cout << "p=" << p << endl; cout << "*p=" << *p << endl; } //函数的定义 int* func() { //定义一个变量 int a = 3; //显示结果 cout << "a=" << a << endl; cout << "a的地址是:" << &a << endl; return &a; }
避免出现野指针的方法:
1、在定义的时候,如果没地方指,就初始化为nullptr。
2、动态分配的内存被释放后,将其置为nullptr。
3、函数不要返回局部变量的地址。
11、函数指针和回调函数
函数指针:
函数的二进制代码存放在内存区四区中的代码段,函数的地址它在内存中的开始地址。如果把函数的地址作为参数,就可以在函数中灵活调用其他函数。
使用函数指针的三个步骤:
1、声明函数指针;
声明普通指针时,必须提供指针的类型。同样声明函数指针时,也必须提供函数类型,函数类型是指返回值和参数列表
#include<iostream> //包含的头文件 using namespace std; //指定缺省的命名空间 //声明函数指针 void (*pfunc)(int, string); //普通函数声明 void func(int no, string str); int main() { int bh = 3; string message = "C++开发者"; //普通函数的函数调用 func(bh, message); //对函数指针赋值 pfunc = func; //语法 : 函数指针名=函数名; //使用函数指针名调用函数 pfunc(bh, message); } //普通函数的定义 void func(int no, string str) { cout << "你好" << no << "号:" << str << endl; }
2、让函数指针指向函数的地址;
3、通过函数指针调用函数。
//对函数指针赋值 pfunc = func; //语法 : 函数指针名=函数名; //使用函数指针名调用函数 pfunc(bh, message);
普通函数的调用方式:
#include <iostream> //包含的头文件 using namespace std; //指定缺省的命名空间 //声明函数 void func(int no, string str); int main() { //声明编号 int bh = 3; //声明信息 string message = "我是C++开发者"; //函数调用 func(bh, message); } //函数定义 void func(int no, string str) { cout << "你好" << no << "号" << str << endl; }
回调函数:
#include <iostream> //包含的头文件 using namespace std; //指定缺省的命名空间 void 个性化表白函数() { //个性化表白的代码 } void 表白神器(个性化表白函数指针p) { 个性化表白函数指针p(); } int main() { 表白神器(个性化表白函数名); }
代码填充
//函数的回调 #include <iostream> //包含的头文件 using namespace std; //指定缺省的命名空间 //回调函数1 void func1() //个性化表白函数 { cout << "我是C++开发" << endl; } //回调函数2 void func2() { cout << "我是C开发者" << endl; } //调用者函数 void show(void(*pf)()) { //工作前的准备 cout << "工作前准备已经完成" << endl; //用函数指针名调用个性化表白函数 pf(); //尾工作 cout << "收尾工作已完成" << endl; } int main() { //调用功能函数 show(func1); }
12、一维数组
数组是一组数据类型相同的变量,可以存放一组数据。
1、创建数组
声明数组的语法:数据类型 数组名[数组长度]
#include <iostream> //包含的头文件 using namespace std; //指定缺省的命名空间 int main() { //创建数组 int bh[3]; //编号 string name[3]; //姓名 //可以通过数组下表访问数组元素,数组下标从0开始. //数组中的每个元素特征和使用方法与单个变量完全相同 bh[0] = 3; //第0个 bh[1] = 5; //第1个 bh[2] = 8; //第2个 cout << "bh[0]=" << bh[0] << endl; cout << "bh[1]=" << bh[1] << endl; cout << "bh[2]=" << bh[2] << endl; cout << endl; //可以使用变量来创建数组 //创建变量i int i; //将i赋值为 表示第0个 i = 0; //将数组下标用变量表示 bh[i] = 3; //将i赋值为1 表示第1个 i = 1; //将数组下标用变量表示 bh[i] = 5; //将i赋值为2 表示第2个 i = 2; bh[i] = 8; i = 0; cout << "bh[0]=" << bh[i] << endl; i = 1; cout << "bh[1]=" << bh[i] << endl; i = 2; cout << "bh[2]=" << bh[i] << endl; }
注意:数组长度必须是整数,可以是常量,也可以是变量和表达式
处理数组的常用方法:使用循序:for循环和while循环都可以
#include <iostream> //包含的头文件 using namespace std; //指定缺省的命名空间 int main() { //创建数组 int bh[3]; //编号 string name[3]; //姓名 //可以通过数组下表访问数组元素,数组下标从0开始. //数组中的每个元素特征和使用方法与单个变量完全相同 for (int i = 0; i < 3; i++) //i要小于数组长度 { bh[i] = 30 + i; //循环第0次,i的值是0,编号是30 循环第1次,i的值是1 编号是31 循环第二次,i的值是2 编号是32 } int i; i = 0; cout << "bh[0]=" << bh[i] << endl; i = 1; cout << "bh[1]=" << bh[i] << endl; i = 2; cout << "bh[2]=" << bh[i] << endl; }
将上述代码继续优化
#include <iostream> //包含的头文件 using namespace std; //指定缺省的命名空间 int main() { //创建数组 int bh[3]; //编号 string name[3]; //姓名 //可以通过数组下表访问数组元素,数组下标从0开始. //数组中的每个元素特征和使用方法与单个变量完全相同 for (int i = 0; i < 3; i++) //i要小于数组长度 { bh[i] = 30 + i; //循环第0次,i的值是0,编号是30 循环第1次,i的值是1 编号是31 循环第二次,i的值是2 编号是32 } /*int i; i = 0; cout << "bh[0]=" << bh[i] << endl; i = 1; cout << "bh[1]=" << bh[i] << endl; i = 2; cout << "bh[2]=" << bh[i] << endl;*/ //使用for循环改写 for (int i = 0; i < 3; i++) { cout << "bh[" << i << "]=" << bh[i] << endl; } }
2、数组的使用
可以通过下标访问数组中的元素,数组下标从0开始
数组中每个元素的特征和使用方法与单个变量完全相同
语法:数组名[数组下标]
3、数组占用内存的情况
用sizeof(数组名)可以得到整个数组占用内存空间的大小(只适用于C++基本数据类型)
#include <iostream> //包含的头文件 using namespace std; //指定缺省的命名空间 int main() { //创建数组 int bh[3]; //编号 string name[3]; //姓名 cout << "数组bh占用的内存空间是:" << sizeof(bh) << endl; }
4、数组的初始化
声明的时候初始化
数据类型 数组名[数组长度] ={值1,值2, ......}
数据类型 数组名[] ={值1,值2,.......}
数据类型 数组名[数组长度] = {0};//把全部元素初始化为0
数据类型 数组名[数组长度] = { };//把全部元素初始化为0
13、一维数组的越界
#include <iostream> using namespace std; int main() { //定义一维数组 int a[5] = { 3,6,9,5,8 }; //用数组表示法操作数组 /*cout << "a[0]的值是:" << a[0] << endl; cout << "a[1]的值是:" << a[1] << endl; cout << "a[2]的值是:" << a[2] << endl; cout << "a[3]的值是:" << a[3] << endl; cout << "a[4]的值是:" << a[4] << endl;*/ //使用for循环优化代码 for (int i = 0; i < 5; i++) { cout << "a[" << i << "]的值是:" << a[i] << endl; } cout << endl; //用指针表示法操作数组 int* p = a; /*cout << "*(p+0)的值是:" << *(p + 0) << endl; cout << "*(p+1)的值是:" << *(p + 1) << endl; cout << "*(p+2)的值是:" << *(p + 2) << endl; cout << "*(p+3)的值是:" << *(p + 3) << endl; cout << "*(p+4)的值是:" << *(p + 4) << endl;*/ //使用for循环优化代码 for (int i = 0; i < 5; i++) { cout << "*(p+" << i << ")的值是:" << *(p + i) << endl; } }
14、解释器和编译器有什么不同?
解释器:解释器一种对代码(或者字节码)进行解释并执行相应的操作的工具;编译器将代码作为输入,并生成目标文件。就C++而言,编译和链接后,将得到一个可执行文件,处理器可直接执行它,而无需做进一步解释
编译器:将C++代码文件作为输入,并生成一个使用机器语言的目标文件。通常代码依赖与库和其他代码文件中的函数。
15、链接器的作用
将编译器生成的目标文件和库文件链接在一起,生成最终的可执行文件或者共享库
16、正常的开发周期包括哪些步骤
编写代码-->通过编译创建目标文件-->通过链接创建可执行文件-->执行应用程序一边进行测试-->调试-->修复代码中的错误并重复这些步骤
17、一维数组的排序
//1.如果函数的返回值<0, 那么p1所指向元素的会被排在p2所指向元素的前面
//2.如果函数的返回值==0, 那么p1所指向的元素与p2所指向的元素的顺序不确定
//3.如果函数的返回值>0, 那么p1所指向的元素会被排在p2所指向元素的后面//qsort()函数用于各种数据类型的数组进行排序
//函数的原型:
// void qsort(voidbase,size_t number,size_t size,int(compar)(const void ,const void));#include <iostream> //包含头文件 using namespace std; //指定缺省的命名空间 //1.如果函数的返回值<0, 那么p1所指向元素的会被排在p2所指向元素的前面 //2.如果函数的返回值==0, 那么p1所指向的元素与p2所指向的元素的顺序不确定 //3.如果函数的返回值>0, 那么p1所指向的元素会被排在p2所指向元素的后面 //qsort()函数用于各种数据类型的数组进行排序 //函数的原型: // void qsort(void*base,size_t number,size_t size,int(*compar)(const void *,const void*)); //声明回调函数 int compasc(const void* p1, const void* p2); int main() { //声明一个整i型数组 int a[8] = { 4,2,7,5,8,6,1,3 }; //函数的原型: // void qsort(void*base,size_t number,size_t size,int(*compar)(const void *,const void*)); //回调函数的调用 qsort(a, sizeof(a) / sizeof(int), sizeof(int), compasc); //显示数组内容 for (int i = 0; i < 8; i++) { //cout << "a[" << i << "]的值是: " << *(a + i) << endl; cout << "a[" << i << "]的值是: " << a[i] << endl; } return 0; } //回调函数的定义:即回调函数实现过程 int compasc(const void* p1, const void* p2) { /*if (*((int*)p1) < *(int*)p2) return -1; if (*(int*)p1 == *(int*)p2) return 0; if (*(int*)p1 > *(int*)p2) return 1;*/ return *((int*)p1) - *((int*)p2); //等同于边代码 }