根据运算符的优先级和结合律,此表达式可以看作 5+( (10 * 20) / 2),结果为105
(a) *vec.begin() //*(vec.begin())
(b) *vec.begin()+1 //(*(vec.begin))+1
可以接受,我们可以自己判断,如果改变了某个运算对象的值,在表达式的其他地方就不再使用这个运算对象,但改变运算对象的子表达式本身就是另外一个子表达式的运算对象时该规则无效。
12/3*4+5*15+24%4/2
添加括号后:( (12 / 3) * 4)+(5 * 15)+( (24%4) / 2) = 91
#include
using namespace std;
int main()
{
int num = 12 / 3 * 4 + 5 * 15 + 24 % 4 / 2;
cout << num;
}
//输出91
(a) -30*3+21/5 //-86
(b) -30+3*21/5 //-18
(c) 30/3*21%5 //0
(d) -30/3*21%4 //-2
#include
using namespace std;
int main()
{
int num;
cin >> num;
if (num % 2)
cout << "奇数";
else
cout << "偶数";
}
当计算的结果超出该类型所能表示的范围时就会产生溢出。
#include
using namespace std;
int main()
{
short a = 32768;
cout << a << endl; //输出-32768
int b = 2147483648;
cout << b << endl; //输出-2147483648
int c = -b - 1;
cout << c; //输出2147483647
}
对于逻辑与&&:当且仅当左侧运算对象为真时才对右侧运算对象求值
对于逻辑或 | |:当且仅当左侧运算对象为假时才对右侧运算对象求值
对于相等性运算符:如果两侧运算对象类型不同,进行类型转换
const char* cp = "Hello World";
if(cp && *cp)
先判断cp,是一个指针,指向了字符数组的第一个元素,不为空,结果为真
接着判断*cp,解引用操作,得到字符'H',为真。
#include
using namespace std;
int main()
{
int n;
while (cin >> n && n != 42)
{ }
}
#include
using namespace std;
int main()
{
int a = 4, b = 3, c = 2, d = 1;
if (a > b && b > c && c > d)
cout << "a>b、b>c、c>d" << endl;
}
根据优先级,先比较 j 和 k 的大小,关系运算符的运算结果是布尔值,如果 j < k,运算结果为true;如果 j >=k ,运算结果为false。接着进行相等性测试,首先布尔值将先转换整型,true转换为1;false转换为0,与i比较是否相等,如果相等,运算结果为true,如果不相等,运算结果为false。
#include
using namespace std;
int main()
{
int i;
double d;
d = i = 3.5; //3 3
i = d = 3.5; //3 3.5
cout << i << " " << d;
}
if (42 = i) //会报错,字面值42是右值
if (i = 42) //i=42,赋值语句结果为左侧运算对象,赋值后为42,非0,因此为真
int main()
{
double dval;
int ival;
int* pi;
dval = ival = pi = 0;
//pi类型时int*型,ival是int型,不能把指针类型的值赋给int
}
改正:
int main()
{
double dval;
int ival;
int* pi;
pi = 0;
dval = ival = 0;
}
(a) if(p = getPtr() != 0)
此表达式中 != 运算符优先级高于 = 运算符,因此会先比较 getPtr( )的返回值与0是否相等,比较的结果是一个布尔值,相等为true,不相等为false,再将结果赋给p,结果为1或0。
这样的过程和结果可能与设想的过程并不一致,因此可以用括号将上述语句修改为
if( (p = getPtr()) != 0)
(b) if(i = 1024)
此表达式为赋值表达式,值为1024,转换为布尔类型永远为true,而期待的可能是比较 i 与1024是否相等,因此我们可以把上述表达式改为
if(i ==1024)
前置递增运算符:j=++i,首先将 i 加1,然后将改变后的对象作为求值结果
后置递增运算符:j=i++,也会将韵算对象加1,但是求值结果是运算对象改变之前那个值的副本
两种运算符必须作用于左值运算对象。前置版本将对象本身作为左值返回,后置版本将对象原始值的副本作为右值返回
建议:如果不需要修改前的值,都采用前置版本。
auto pbeg = v.begin();
while (pbeg != v.end() && *pbeg >= 0)
cout << *pbeg++ << endl;
如果改为前置递增运算符,第一个元素的值将无法输出,而且如果序列中没有负值,后面可能试图解引用一个不存在的元素。
(a) ptr != 0 && *ptr++
如果指针不是空指针,就将指针指向后一位,接着返回指针改变之前指向的对象,若未非0,表达式为真
(b) ival++ && ival
首先ival自增1,然后返回ival原始值的副本,如果不为0,就对右边ival求值,此时的ival应是加1之后的,如果不为0,表达式为真
(c) vec[ ival++] <= vec[ival]
表达式的求值顺序未知,若是先求左侧,右侧的ival就应该是加了1以后的,若是先求右侧,ival就应该是原始值,修改如下:
++ival;
vec[ival] <= vec[ival+1] ;
(a) *iter++;
合法,自增运算符优先级大于解引用,iter++使iter加1,接着返回iter原始值的副本作为iter++表达式的结果,接着*解引用的是未增加之前的iter副本
(b) (*iter)++;
不合法,先解引用iter,得到了一个sring元素,string不能自增,不能通过编译
(c) *iter.empty()
不合法,迭代器没有empty()成员函数
(d) iter->empty();
合法,iter->empty()等价于(*iter).empty(),如果iter指向的string为空就返回true,否则返回false
(e) ++*iter;
不合法,原因同b,不能通过编译
(f) iter++->empty();
合法,先判断迭代器指向的值是否为空,再对迭代器加1,指向下一个元素
#include
#include
using namespace std;
int main()
{
vector sp{ 1,2,3,4,5,6 };
cout << "Original data is:";
for (auto it : sp)
cout << it << " ";
cout << endl;
cout << "After changing is:";
for (auto it : sp)
cout << ((it % 2) ? 2 * it : it)<<" ";
}
只用条件运算符:
#include
#include
using namespace std;
int main()
{
int grade = 0;
cin >> grade;
string finalgrade = (grade > 90) ? "high pass"
: (grade > 75) ? "pass"
: (grade > 60) ? "low pass" : "fail";
cout << finalgrade;
}
使用if语句
#include
#include
using namespace std;
int main()
{
int grade = 0;
cin >> grade;
string finalgrade;
if (grade > 90)
cout << "high pass";
else if (grade > 75)
cout << "pass";
else if (grade > 60)
cout << "low pass";
else
cout << "fail";
cout << finalgrade;
}
if语句更容易理解,可读性比条件运算符多次嵌套好。
string s = "word";
string p1 = s + s[s.size () - 1] == 's' ? " " : "s";
根据运算符优先级,将首先通过s.size()求出s中字符的个数为4,接着s[4-1]访问s中下标为3的字符'd',将字符字面值与string对象s相加,相加后的string对象s为"wordd",接着与字符's'比较是否相等,但是string对象无法与字符字面值s进行==比较,因此错误。
修改如下:
string p1 = s + (s[s.size () - 1] == 's' ? " " : "s");
上述过程到访问s中下标为3的字符时,若字符为's',则不向string对象s加入任何值,若字符不为's',则向string对象s结尾加上's‘。
finalgrade = (grade > 90) ? "high pass"
: (grade < 60) ? "fail" : "pass";
左边的条件运算构成了右边的条件运算的判断条件的表达式,如果输入的值大于90,表达式的结果就应该是”high pass",字符串转换成布尔类型是有限制的,显然此字符串不可以转换,会出错。
根据运算符优先级,先对'q'按位取反,
在内存中字符q为:00000000 00000000 00000000 01110001
按位取反后为 : 11111111 11111111 11111111 10001110
按位左移6位后为: 11111111 11111111 11100011 10000000
是一个负数,在内存中以补码存取,如果输出,输出的是化为原码的十进制数
原码 :10000000 00000000 00011100 10000000
化为十进制后的数为 -7296
不确定30个学生的成绩都能准确表示,因为unsigned int只能确保占用16位,而此例至少需要30位,因此选择unsigned long。
#include
using namespace std;
int main()
{
//3: 00000000 00000000 00000000 00000011
//7: 00000000 00000000 00000000 00000111
unsigned long ul1 = 3, ul2 = 7;
cout << (ul1 & ul2); //3
cout << (ul1 | ul2); //7
cout << (ul1 && ul2); //1
cout << (ul1 || ul2); //1
}
后两个表达式的运算符是逻辑运算符。
#include
using namespace std;
int main()
{
cout << "bool的大小为:" << sizeof(bool) << endl; //1
cout << "char的大小为:" << sizeof(char) << endl; //1
cout << "short的大小为:" << sizeof(short) << endl; //2
cout << "int的大小为:" << sizeof(int) << endl; //4
cout << "long的大小为:" << sizeof(long) << endl; //4
cout << "long long的大小为:" << sizeof(long long) << endl; //8
cout << "float的大小为:" << sizeof(float) << endl; //4
cout << "double的大小为:" << sizeof(double) << endl; //8
}
#include
using namespace std;
int main()
{
int x[10];
int* p = x;
cout << sizeof(x) / sizeof(*x) << endl; //10
cout << sizeof(p) / sizeof(*p) << endl; //2
}
第一个表达式计算的是数组x中的元素数量
第二个表达式的sizeof(p)计算的是一个指针的大小,由于我的电脑是64位的,因此大小为8,sizeof(*p)计算的是指针所指向的对象所占空间大小,为4。
(a) sizeof x+y //(sizeof x)+y
(b) sizeof p-> men[i] //sizeof (p->men[i])
(c)sizeof a
(d)sizeof f() //sizeof (f())
#include
#include
using namespace std;
int main()
{
vector ivec{1,2,3,4,5};
vector::size_type cnt = ivec.size();
for (vector::size_type ix = 0; ix != ivec.size(); ++ix, --cnt)
ivec[ix] = cnt;
for (auto it : ivec)
cout << it << " ";
}
//输出5 4 3 2 1
个人认为如果使用了后置版本就会把原始的值存储下来,而前置版本则是直接返回改变了以后的运算对象,但是我们并不需要原始值了,因此使用后置版本是一种浪费,其他原因暂时想不到,而用后置改写也改动不大。
#include
#include
using namespace std;
int main()
{
vector ivec{ 1,2,3,4,5 };
vector::size_type cnt = ivec.size();
for (vector::size_type ix = 0; ix != ivec.size(); ix++, cnt--)
ivec[ix] = cnt;
for (auto it : ivec)
cout << it << " ";
}
如上,改变之后的版本输出依然正确。
int main()
{
constexpr int size = 5;
int ia[size] = { 1,2,3,4,5 };
for (int* ptr = ia, ix = 0;
ix != size && ptr != ia + size;
++ix, ++ptr)
{/* ... */ }
}
ptr是一个指针,被初始化为指向数组ia的第一个元素,当ix的值不等于数组的维度并且指针没有指向数组之外时,循环才继续,每次循环结束,ix和指针都自增1。
someValue ?++x, ++y : --x, --y
由于逗号表达式优先级最低,此表达式可以看成
(someValue ?++x, ++y : --x), --y
如果someValue为真,x自增1,y自增1,后又自减1,y的值不变
如果someValue为假,x自减1,y自减1
float fval; int ival; double dval; char cval;
(a) if (fval) //fval如果是0,则转换为false,否则转换为true
(b) dval = fval + ival; //ival首先被转换为float,将fval+ival的结果转换为double
(c) dval + ival * cval; //cval先整型提升成int,与ival相乘后的结果被转换成double
char cval; int ival; unsigned int ui; float fval; double dval;
(a) cval = 'a' + 3;
//'a'整型提升为int,与3相加后的结果转换为char赋给cval
(b) fval = ui - ival * 1.0;
//ival转换为double,与1.0相乘,ui转换为double,与ival*1.0相减,相减后结果转换为float赋给fval
(c) dval = ui * fval;
//ui转换为float,与fval相乘,乘积转换为double赋给dval
(d) cval = ival +fval + dval;
//ival转换为float,与fval相加后的结果转换为double,与dval相加后的结果转换为char,赋给cval
i *= static_cast
(d);
#include
using namespace std;
int main()
{
int i = 2;
double d = 2.5;
i *= d; //5
i *= static_cast(d); //4
cout << i ;
}
原表达式输出结果为5,更改后为4,因为原表达式i类型转换为了double型,执行浮点型的乘法,而更改后用强制类型转换将d转换为int型,执行整型的乘法。
int i; double d; const string *ps; char *pc; void *pv;
(a) pv = (void*)ps; // pv = const_cast
(ps); (b) i = int(*pc); // i = static_cast
(*pc) (c) pv = &d; // pv = static_cast
(&d) (d) pc = (char*) pv; // pc = static
(pv)
double slope = static_cast
( j / i );
将 ( j / i )的值强制转换为double类型,赋给slope