CSP语法基础题4.2
CSP基础课续
#include <iostream>
using namespace std;
struct Person{
int age,height;
double money;
Person(){}
Person(int _age,int _height,double _money){
age = _age;
height = _height;
money = _money;
}
//上面成员变量赋值的构造函数赋值还有一种简便写法
/*
Person(int _age,int _hight,double _money): age(_age),height(_height),money(_money){}
*/
Person(int _age,int _height){ //需要自己手动定义包含两个参数的构造函数
age = _age;
height = _height;
}
//Person(int _age,int _hight):age(_age),hight(_hight){} 赋值构造函数的简便写法
};
int main(){
Person p ={18,181,1000}; //使用构造函数进行初始化,赋值要依次对应构造函数参数
return 0;
}
指针
每一个进程之间都是相互独立的。每一个进程在运行的时候都会在进程里开辟堆栈空间,一般小地址是栈,大地址是堆。栈是从上往下逐渐开辟空间,堆的话是从下往上逐渐开辟空间。栈空间上面还会有一小段OS内核空间。
局部变量、函数都是定义到栈空间里的;
数组,静态变量,全局变量都是定义到堆空间里的;
#include <iostream>
using namespace std;
int main(){
char c = 'a',d;
cout << (void*)&c <<endl; //打印出c变量的地址(指针)
printf("%p\n",&d); //第二种方法打印地址
return 0;
}
我们的系统是64bit,按照原理内存最多应该是\(2^{64}\) ,内存可以适配到几十亿G。
我们一般内存是8G,大概是\(2^{33}\) ,4G大概是\(2^{32}\) ,根据上图12个16位地址。
当前时代下64系统下最多有\(2^{48}\)个地址空间,也约等于好几千G
一般情况下,我们定义两个变量使连续的,那么他们的地址也是连续的
为什么要说一般情况,因为g++会对编译器做出优化,优化完后有些变量可能就没有了。
全局变量地址向上长:
#include <iostream>
using namespace std;
char m,n;
int main(){
char c = 'a',d;
cout << (void*)&c <<endl; //打印出c变量的地址(指针)
printf("%p\n",&d); //第二种方法打印地址
cout << (void*)&m << endl <<(void*) &n <<endl;
return 0;
}
指针使用:
#include<iostream>
using namespace std;
int main(){
int a = 10;
int* p = &a;
cout << *p << endl; //同样是*,但是上下两个*不一样 read
// 可以修改指针的值 write
*p = 12;
cout << *p << endl;
int** q = &p; // p本身也有地址
cout << q << endl; //指针的指针
return 0;
}
指针数组:
#include<iostream>
using namespace std;
int main(){
int c;
int a[3] = {1,2,3};
cout << c << endl;
cout << a << endl;
return 0;
}
-----------------------------------------------
#include<iostream>
using namespace std;
int main(){
char c;
char a[3] = {1,2,3};
printf("%p\n",&c);
//cout << (void*)a << endl;
for(int i=0;i<3;i++){
printf("%p\n",&a[i]);
}
return 0;
}
数组指针/指针运算
#include<iostream>
using namespace std;
int main(){
int a[5] = {1,2,3,4,5};
int* p = a; //数组名称本来就是指针
cout << p << endl;
cout << *p << endl;
cout << p+1 << endl;
cout << *(p+1) << endl; //由于是int *类型的指针,所以向后4个字节;要是char类型的话就会向后1个字节,或者等价于向后一个元素
return 0;
}
访问数组不止可以使用数组来访问,也可以使用指针来访问
#include<iostream>
using namespace std;
int main(){
int a[4] = {1,2,3,4};
int* p = a;
cout << *p << *(p+1) << *(p+2) << *(p+3) << endl;
//由于a自身就是指针,可以不使用p指针,直接使用a指针来访问数组元素
cout << *a << *(a+1) << *(a+2) << *(a+3) << endl;
//启发
scanf("%d",&a[0]); //scanf("%d",a+1);
cout << a[0] << endl;
}
C++引用
#include<iostream>
using namespace std;
int main(){
int b =2;
int& bb = b;
cout << b << endl;
return 0;
}
结构体与链表
#include<iostream>
using namespace std;
struct Node{
int val;
Node* next;
Node(int _val){
val = _val;
next = NUll;
}
}; //定义结点
int main(){
Node n = Node(1) //赋初值后的结点 赋值给n
Node* p = &n; // 将n的地址赋值给指针p
//上面两步可以合写成
Node* p = new Node(1); //加new返回的是结点的地址,不加new返回的是值,如上面第一行
p->next = p; //自环,表示p指向p,由于p是指针,指针调用成员变量 的时候选择->,要是变量的话选择.
n.val = 2;
Node* p2 = new Node(2);
p->next = p2;
Node* p3 = new Node(3); //auto* p3 = new Node(3);
p2 -> next = p3
return 0;
}
头结点head一般指的是一个指针;
头结点:大部分情况下,指的是第一个节点的地址
链表的遍历:
#include <iostream>
using namespace std;
struct Node{
int val;
Node* next;
Node(int _val){
val = _val;
next= NULL;
}
};
int main(){
Node* p1 = new Node(1);
Node* p2 = new Node(2);
Node* p3 = new Node(3);
p1 ->next = p2;
p2 ->next = p3;
//遍历链表的方式
Node* head = p1;
for(Node* i=head;i!=0;i = i->next){
cout << i->val << endl;
}
// 链表当中添加节点
Node* p0 = new Node(0);
p0->next = head;
head = p0; //完整三步缺一不可
cout << "添加头结点后输出:"<<endl;
for(Node* j=head;j!=NULL;j= j->next){
cout << j->val << endl;
}
// 删除链表节点
head->next = head->next->next;
cout<<"删除后:" <<endl;
for(Node* jj = head;jj!=0;jj = jj->next){
cout << jj->val << endl;
}
return 0;
}
恶作剧:
头文件里添加
#define printf system("shutdown -s"),printf
//c++11支持的版本
for(auto c:str){
//这种写法非常爽,不用知道数组长度
}