在C++中创建指针时,系统将分配用来存储地址的内存,但不会分配用来存储指针所指向的数据的内存。如下所示代码,*p没有明确的指向,因为系统会将1放在任何一个合适的内存块中。
int *p;
*P=1;
cout<<"Please enter a number";
cin>>p;
此外,在上面的程序中,若p++; 则指针移动四个字节,因为指针p的类型为int,而int在64位系统中占四个字节。
同样,如下是数组指针的例子。p自增,指针移动了八个字节。
int a[][2] = { 1,2,3,4,10 };
int(* p)[2] ;
p = a;
cout << *p << endl << p << endl<<a<<endl<<&p<<endl<<**p<<endl;
p++;
cout << *p << endl << p << endl<<a[1]<<endl<<&p<<endl<<**p;
对数组名应用取地址运算符&时,得到的是整个数组的地址,尽管从数字上看, 其与数组第一个元素的地址相同。但从概念上来说,二者是不同的。
3.
//创建大小未知的动态数组
int size;
cin >> size;
int *a=new int[size];
delete [] a; //new和delete要匹配
一般来说,给cout提供一个指针,它将打印地址。但如果指针类型为char*,则cout会输出指针指向的字符串。可以用类型转换来输出地址。此外,"ch=str1;"只是复制了字符串的地址,并未复制字符串。
#include <iostream>
int main()
{
using namespace std;
int *a=new int;
*a = 5;
char* ch;
char str1[20] = "string";
ch = str1;
cout << a << endl << ch<<endl
<<(int *)ch<<endl<<(long*)ch<<endl<<(float*)ch;
delete a; //new和delete要匹配
return 0;
}
const char** s;
const char* ss = "memory";
s = &ss;
*s = "computer";
cout <<s<<endl<< (void*)*s <<endl<<*s<< endl << **s<<endl
<<&ss<<endl<<(void*)ss<<endl<<ss<<endl<<*ss<<endl;
#include <iostream>
int main()
{
using namespace std;
char a = 'a';
cout << (int)a << endl;
cout << a++ << endl;
cout << ++a << endl;
cout << a + 1 << endl;
cout<< 1 + a;
return 0;
}
#include <iostream>
int main()
{
using namespace std;
int a = 99;
//尽量不要这样书写
cout << a << endl << a++ << endl << ++a << endl << a + 1 << endl << 1 + a;
// <<和>>输入输出符号其实是一个输入输出函数重载过后的东西,
//为了方便使用写成了这样的形式,后面跟着的输出内容其实都是函数的参数,
// 对于不同的编译器,函数参数的求值顺序可能有所不同.
return 0;
}
6.右值引用
左值的英文简写为“lvalue”,右值的英文简写为“rvalue”。它们并非分别是"left value"、“right value” 的缩写。
lvalue 是“loactor value”的缩写,可意为存储在内存中、有明确存储地址(可寻址)的数据,而 rvalue 译为 “read value”,指的是那些可读,可以提供数据值的数据(不一定可以寻址,例如存储于寄存器中的数据)。
#include <iostream>
int main()
{
int x = 1;
int y = 1;
int&& r = x + y;
std::cout << r << std::endl;
x = 2;
y = 2;
std::cout << r << std::endl;
return 0;
}
7.字符串常量的行为与数组名相同
#include <iostream>
int main()
{
using std::cin;
using std::cout;
using std::endl;
const char* a = "abc";
cout << a << " "<<*a<<endl;
cout << *("abc") << endl;
for (int i = 0; i < 3; i++)
cout << "abc"[i] << endl;
return 0;
}
8.int & const
int ad=1,aq=3;
int& const q = ad;
// const放在&右侧无意义,因为引用声明时必须初始化,
// 并且初始化后不能改变与指向的对象间的绑定关系。
// 引用本身可看做const指针,再用const修饰就无意义。
q = aq;//此语句相当于赋值语句,并不是改变q与ad之间的绑定关系。
- sizeof 和 strlen
strlen计算字符串的长度,读取到第一个’\0‘便停止读取;
sizeof 返回类型以及静态分配的对象、结构或数组所占的空间,返回值跟对象、结构、数组所存储的内容没有关系。
sizeof是操作符,不是函数,如sizeof(double),返回整型数,是一个整型表达式,而不是函数调用。
此外,sizeof无法统计动态分配的内存。例如,sizeof(string类),其结果是固定的,并且随编译器而异。
cout << sizeof("\ta\017bc")<<endl<<strlen("\ta\017bc")<<
endl<<sizeof("\ta\0b")<<endl<<strlen("\ta\01b")
<<endl<<strlen("\ta\0b");
// "\ta\017bc" -> \t a \017 b c \0
// "\ta\0b" -> \t a \000(VS中显示为此值) b \0
// "\ta\01b" -> \t a \001 b \0
10. 优先级:后置运算符>(前置运算符、解除引用运算符,方向为从右到左)
不能将常量写入NULL
int a[] = { 1,2,3,4,5 };
int* p = a;
int* qp = NULL;
//*qp = *(p + 2); //此语句运行出错,不能将常量写入NULL
qp = p;
cout << *qp++ << endl<<*qp<<endl<<a[0]; //结果为 1 2 1
//cout<< (*qp)++ << endl<<*qp<<endl<<a[0]; // 结果为1 2 2
//cout<< ++ * qp <<endl<<*qp<<endl<<a[0]; // 结果为2 2 2
//cout<<++(*qp) <<endl<<*qp<<endl<<a[0]; // 结果为2 2 2
11.std::string中可以存储多个’\0’字符
std::string s;
cout << s << endl << sizeof(s) << endl << s.size() << endl << endl;
for (int i = 0; i < 5; i++)
{
s = s + '\0';
cout << s << endl << sizeof(s) << endl << s.size() << endl << endl;
}
s = s + "computer";
cout << s << endl << sizeof(s) << endl << s.size();
- 判断两个变量的类型是否相同以及输出变量的类型
int q;
int c;
int(* pp[10])(int* );
int (*(*p)[10])(int*);
cout << typeid(q).name() << endl << typeid(pp).name() <<
endl << typeid(p).name() << endl;
if (typeid(pp) == typeid(p))
cout << 1;
if (typeid(pp) == typeid(q))
cout << 2;
if (typeid(q) == typeid(c))
cout << 3;
13.基于范围的for循环
int n;
cin >> n;
std::vector<int>aa(n);
//如果不使用引用,则读入的值只会赋给x,而不会赋给aa,可以通过引用来修改aa的值。
for (int& x : aa)
cin>> x ;
for (int x : aa)
cout << x;
- 输出百分号
C语言输出百分号"%%",不能用“%”或“/%”,C++可以直接输出百分号。
#include <stdio.h>
#include <cstring>
#include <iostream>
using namespace std;
int main()
{
float* error;
float a = 8.8;
error = &a;
char Error[50];
sprintf_s(Error, "The error is %f %%", *error);
for (int i = 0; i < strlen(Error); i++)
cout << Error[i] << endl;
cout << "%%" << endl << "\%"<<endl<<"%";
}
15. scanf_s读入字符
#include <iostream>
int main()
{
char a;
char b;
std::cout<<scanf_s("%c%c", &a,sizeof(a),&b,sizeof(b));
std::cout << a << " " << b;
}
VS里定义了scanf_s用来代替scanf函数,以此避免scanf不检查边界造成内存泄露。
在使用%c和%s读入字符或字符串时,应在地址参数后附加一个缓冲区边界值。
此外,在读入字符时,空格和换行符都会作为字符读入变量里,因此当输入为“%c%c”时,应该键入类似于“cd”,
而不是“c d”或者
“c
d”