表达式5+10*20/2的求值结果是多少?
105
在下列表达式合理位置添加括号,使得添加括号后的运算对象组合顺序与添加前一致
(a)*vec.begin() (b)*vec.begin()+1
成员选择运算符.
优先级>解引用运算符*
>加法运算符+
,所以:
(a):表示先获得指向vec[0]
的指针,再解引用获得值vec[0]
。添加括号:*(vec.begin())
;
(b):表示先获得指向vec[0]
的指针,再解引用获得值vec[0]
,最后加1。添加括号:*(vec.begin())+1
;
验证代码
#include
#include
using std::cout;
using std::endl;
using std::vector;
int main()
{
vector<int> vec(5, 0);
cout << *vec.begin() << endl;
cout << *(vec.begin()) << endl;
cout << *vec.begin() + 1 << endl;
cout << *(vec.begin()) + 1 << endl;
system("pause");
return 0;
}
C++语言没有明确规定大多数二元运算符的求值顺序,给编译器优化留下了余地。这种策略实际上是在代码生成效率和程序潜在缺陷之间进行了权衡,你认为这可以接受吗?请说出你的理由
可以接受。程序潜在缺陷是可以在编程时调整以避免的,而代码效率相较之下更为重要。
在下面表达式中添加括号,说明其求值过程及最终结果。编写程序验证结果。
12/3*4+5*15+24%4/2
((12/3)*4)+(5*15)+((24%4)/2)
#include
using std::cout;
using std::endl;
int main()
{
cout << 12 / 3 * 4 + 5 * 15 + 24 % 4 / 2 << endl; //91
cout << ((12 / 3) * 4) + (5 * 15) + ((24 % 4) / 2) << endl; //91
system("pause");
return 0;
}
写出下列表达式的求值结果:
(a)-30*3+21/5 (b)-30+3*21/5
(a)30/3*21%5 (b)-30/3*21%4
(a)-86 (b)-18
(a)0 (b)-2
验证代码
#include
using std::cout;
using std::endl;
int main()
{
cout << -30 * 3 + 21 / 5 << endl; //-86
cout << -30 + 3 * 21 / 5 << endl; //-18
cout << 30 / 3 * 21 % 5 << endl; //0
cout << -30 / 3 * 21 % 4 << endl; //-2
system("pause");
return 0;
}
写出一条表达式用于确定一个整数是奇数还是偶数。
i % 2 ! = 0 ? “odd” : “even”
溢出是何含义?写出三条将导致溢出的表达式。
计算机计算结果超出该类型所能表示的范围。
#include
using std::cout;
using std::endl;
int main()
{
int a = 2147483647;
cout << ++a << endl; //-2147483648
unsigned int b = 4294967295;
cout << -b << endl; //1
short c = 32767;
cout << ++c << endl; //-32768
system("pause");
return 0;
}
说明在逻辑与、逻辑或及相等性运算符中运算对象的求值顺序。
解释下面的if语句中条件部分判断过程
const char*cp=“Hello World”;
if(cp && *cp);
首先判断cp是否为空字符串,如果不为空字符串,解引用cp,判断cp[0]
是否为真。
为while 循环写一个条件,使其从标准输入中读取整数,遇到 42 时停止。
#include
using std::cin;
using std::cout;
using std::endl;
int main()
{
int i = 0;
while (cin >> i && i != 42)
{
cout << i << endl;//输入:45 88 21 42;输出:45 88 21
}
system("pause");
return 0;
}
书写一条表达式用于测试4个值a、b、c、d的关系,确保a大于b、b大于c、c大于d。
a>b && b>c && c>d
假设i、j 和k 是三个整数,说明表达式 i != j < k 的含义。
首先,不相等运算符优先级低于小于运算符,所以先判断j
在下述语句中,当赋值完成后i和d的值分别为多少?
int i; double d;
(a) d=i=3.5; (b) i=d=3.5;
(a)i=3,d=3
(b)i=3,d=3.5
验证代码
#include
using std::cout;
using std::endl;
int main()
{
int i;
double d;
d = i = 3.5;
cout << i << " " << d << endl; //3 3
i = d = 3.5;
cout << i << " " << d << endl; //3 3.5
system("pause");
return 0;
}
执行下述if语句后将发生什么情况?
if(42=i)//…
if(i=42)//…
第一句将报错,42不可修改,不能作为左值;
第二句赋值等价于:i=42;if(i)//…即if将永远判断为真(除非修改i的值为0)。
下面的赋值是非法的,为什么?如何修改?
double dval; int ival; int *pi;
dval=ival=pi=0;
pi是指向int类型的指针,无法实现int到int*类型的转换。
可以修改为:dval=ival=*pi=0;
即将pi指向的int类型赋值为0.
尽管下面的语句合法,但他们实际执行的行为可能和预期不一样,为什么?如何修改?
(a) if(p=getPtr()!=0)\\...
(b) if(i=1024)\\...
(a)由于赋值运算符优先级小于不等运算符,所以实际上先判断的是getPtr()!=0
,赋值给p的是返回得到的bool值,可修改为:if((p=getPtr())!=0)
;
(b)实际上执行过程是将1024赋值给i,然后判断if(i)
,当i不为0时将永远判断为真,可修改为:if(i==1024)
说明前置运算符和后置运算符的区别。
前置运算符先将对象加一然后返回;后置运算符是先返回初始对象副本,然后将对象加一。
#include
using std::cout;
using std::endl;
int main()
{
int a = 0, b = 0;
cout << ++a << endl; //1
cout << b++ << endl; //0
system("pause");
return 0;
}
如果132页那个输出vector对象元素的while循环使用前置递增运算符,将得到什么结果?
整体解引用的地址将后移一个单位,原本解引用范围为0->(size-1),现在为1->size
假设 ptr 的类型是指向 int 的指针、vec 的类型是vector、ival 的类型是int,说明下面的表达式是何含义?如果有表达式不正确,为什么?应该如何修改?
(a) ptr!=0 && *ptr++
(b) ival++ && ival
(c) vec[ival++]<=vec[ival]
(a)若ptr不为空指针,判断ptr当前指向值是否不为零,且ptr向后移动一个单位;
(b)先判断ival的值是否不为零,ival+1,然后判断ival加一后的值是否不为零;
(c)实际上是比较vec[ival]小于等于vec[ival+1]是否为真。
假设 iter 的类型是 vector::iterator, 说明下面的表达式是否合法。如果合法,表达式的含义是什么?如果不合法,错在何处?
(a) *iter++; (b) (\*iter)++;
(c) *iter.empty(); (d) iter->empty();
(e) ++*iter; (f) iter++->empty();
(a)合法,先将iter后移一个单位,返回iter初始值并对初始值解引用;
(b)不合法,iter解引用后为string类型,不能使用递增运算符;
(c)不合法,成员选择运算符优先级高于解引用,而iter没有empty成员函数;
(d)合法,等同于(*iter).empty()
;
(e)不合法,string不能使用递增运算符;
(f)合法,先调用(*iter).empty()
,再将iter后移一个单位。
编写一段程序,使用条件运算符从vector中找出那些元素的值是奇数,然后将这些奇数值翻倍.
#include
#include
using std::cout;
using std::endl;
using std::vector;
int main()
{
vector<int> v(10);
int count = 1;
for (auto &i : v)
{
i = (count % 2) ? 2 * count : count;
count += 1;
cout << i << " ";//2 2 6 4 10 6 14 8 18 10
}
system("pause");
return 0;
}
本节的示例程序将成绩划分为high pass、pass 和 fial 三种,扩展该程序使其进一步将 60 分到 75 分之间的成绩设定为 low pass。要求程序包含两个版本:一个版本只使用条件运算符;另一个版本使用1个或多个if语句。哪个版本的程序更容易理解呢?为什么?
if版本逻辑结构清晰,更容易理解。
#include
using std::cout;
using std::endl;
void test01(int grade)
{
cout << ((grade > 90) ? "high pass" : (grade > 75) ? "pass"
: (grade < 60) ? "fail"
: "low pass")
<< endl;
}
void test02(int grade)
{
if (grade > 90)
cout << "high pass" << endl;
else
{
if (grade > 75)
cout << "pass" << endl;
else
{
if (grade < 60)
cout << "fail" << endl;
else
cout << "low pass" << endl;
}
}
}
int main()
{
int grade1 = 93;
int grade2 = 80;
int grade3 = 66;
int grade4 = 58;
test01(grade1);//high pass
test02(grade1);//high pass
cout << '\n';
test01(grade2);//pass
test02(grade2);//pass
cout << '\n';
test01(grade3);//low pass
test02(grade3);//low pass
cout << '\n';
test01(grade4);//fail
test02(grade4);//fail
cout << '\n';
system("pause");
return 0;
}
因为运算符优先级问题,下面这条表达式无法通过编译。根据4.12节的表指出问题在哪里,如何修改?
string s=“word”;
string p1=s+s[s.size()-1]==‘s’?“”:“s”;
加法运算符的优先级高于条件运算符,所以本语句首先执行s+s[s.size()-1]
可修改为:string p1=s+(s[s.size()-1]=='s'?"":"s");
本节的示例程序将成绩划分为 high pass、pass、和fail三种,它的依据是条件运算符满足右结合律。假如条件运算符满足的是左结合律,求值的过程将是怎样的?
没懂(
如果一台机器上int占32位、char占8位,用的是Latin-1字符集,其中字符’q’的二进制形式是01110001,那么表达式~‘q’<<6的值是什么?
首先提升为int类型:
00000000 00000000 00000000 01110001
然后取反:
11111111 11111111 11111111 10001110
最后向左移动6位:
11111111 11111111 11100011 10000000
在本节关于测验成绩的例子中,如果使用unsigned int作为quiz1的类型会发生什么情况?
unsigned int类型只能占用16位,无法完成统计30个学生成绩的任务,会导致数据丢失。
下列表达式的结果是什么?
usigned long ull=3,ul2=7;
(a) ul1 & ul2;
(b) ul1 | ul2;
(c) ul1 && ul2;
(d) ul1 || ul2;
(a)表示对ul1和ul2进行按位与操作:
(前24位均为0)00000011
&
(前24位均为0)00000111
所得结果为:
(前24位均为0)00000011
(b)表示对ul1和ul2进行按位或操作:
(前24位均为0)00000011
|
(前24位均为0)00000111
所得结果为:
(前24位均为0)00000111
(c)表示对ul1和ul2进行逻辑与操作,由于都不为零,所以结果为1.
(d)表示对ul1和ul2进行逻辑或操作,由于不都为零,所以结果为1.
编写一段程序,输出每一种内置类型所占空间大小
#include
using std::cout;
using std::endl;
int main()
{
cout << sizeof(bool) << endl; //1
cout << sizeof(char) << endl; //1
cout << sizeof(short) << endl; //2
cout << sizeof(int) << endl; //4
cout << sizeof(long) << endl; //4
cout << sizeof(long long) << endl; //8
system("pause");
return 0;
}
推断下面代码输出结果并说明理由。实际运行这段程序,结果和你想象的一样吗?如果不一样,为什么?
int x[10];int *p=x;
cout<<sizeof(x)/sizeof(*x)<<endl;
cout<<sizeof(p)/sizeof(*p)<<endl;
sizeof(x)/sizeof(*x)得到的结果是数组的大小,即10;
sizeof§/sizeof(*p)=指针p的大小/指针p指向空间的大小,4/4=1;
根据p142页的表,在下述表达式的适当位置添加括号,使得加上括号之后的表达式含义和原来相同。
(a) sizeof x + y (b) sizeof p->mem[i]
(c) sizeof a < b (d) sizeof f()
(a)sizeof优先级高于加法运算符,所以先执行sizeof。添加括号:sizeof(x)+y;
(b)sizeof优先级低于成员选择运算符。添加括号:sizeof(p->mem[i]);
(c)sizeof优先级高于关系运算符。添加括号:sizeof(a) (d)sizeof优先级低于函数调用运算符。添加括号:sizeof( f() ).
本节程序使用了前置版本的递增运算符和递减运算符,解释为什么要用前置版本而不用后置版本。要想使用后置版本的递减递增运算符需要做哪些改动?使用后置版本重写本节程序。
for循环中执行的语句顺序为:
#include
#include
using std::cout;
using std::endl;
using std::vector;
int main()
{
vector<int> ivec(10);
vector<int>::size_type cnt = ivec.size();
for (vector<int>::size_type ix = 0; ix < ivec.size(); ix++, cnt--)
{
cout << "ivec[" << ix << "]: " << cnt << endl;
ivec[ix] = cnt;
}
system("pause");
return 0;
}
输出:
ivec[0]: 10
ivec[1]: 9
ivec[2]: 8
ivec[3]: 7
ivec[4]: 6
ivec[5]: 5
ivec[6]: 4
ivec[7]: 3
ivec[8]: 2
ivec[9]: 1
解释下面这个循环的含义。
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)
{/*...*/}
遍历数组ia
根据p147页的表说明下面这条表达式的含义
someValue ? ++x, ++y : --x, --y
首先逗号运算符优先级最低,接着是三目运算符。从右向左看,表达式可以分割为:( someValue ? ++x, ++y : --x), --y;
也就是说如果someValue为真,则执行语句:++x,++y,–y
如果someValue为假,则执行语句:–x,–y。
根据本节给出的变量定义,说明在下面的表达式中将发生什么样的类型转换:
(a) if(fval) (b) dval=fval+ival; (c)dval+ival*cval
(a)float转bool
(b)先执行加法运算符,即int转float,加法得到float类型赋值时转为double
(c)先执行乘法,char转int,乘法得到的int类型在执行加法时转为double
假设有如下定义:
char cval; int ival; unsigned int ui;
float fval; double dval;
请回答在面的表达式中发生了隐式类型转换吗?如果有,指出来
(a) cval='a'+3 (b) fval=ui-ival*1.0
(c) dval=ui*fval (d) cval=ival+fval+dval
(a)字符’a’先转化为int类型执行加法,得到int类型在赋值过程中转化为char
(b)先执行乘法,ival提升为double以后执行乘法,ui也提升为double然后执行减法,赋值过程中转为float
(c)unsigned int类型转float执行乘法,赋值时转为double
(d)int转float执行加法,再转double执行加法,赋值时转char
假设i是int类型,d是double类型,书写表达式i *= d使其执行整数类型的乘法而非浮点数的乘法。
i*=static_cast(int)d
用命名的强制转化类型改写下列旧式的转化语句。
int i;double d;const string *ps;char *pc;void *pv;
(a) pv=(void *)ps; (b) i=int(*pc);
(c) pv=&d; (d) pc=(char*)pv;
(a)pv=const_cast
(b)i=static_cast
(c)pv=static_cast
(d)pc=reinterpret_cast
说明下面这条表达式的含义。
double slope=static_cast(j/i);
将j/i的结果强制转换为double类型然后赋值给slope。