程序设计基本概念
一、赋值语句
1.C/C++ code
int i = 1;
void main()
{
int i = i;
}
在C++中,这样的赋值操作时合法的,int i = i,i变量从声明的那一刻起就是可见的,main()里的i不是1,因为它与mian()外的i无关,而是一个未定义的值。
2.#include <iostream>
using namespace std;
int main()
{
int x =2,y,z;
x *= (y = z = 5);//5赋值给z,z再赋值给y,x = x * y = 10;
cout << x << endl;
z = 3;
x == (y = z); //z赋值给y,看x与y是否相等,对x的值不影响
cout << x << endl;
x = (y == z); //看y和z的值是否相等,相等返回布尔值1,不相等返//回0,y和z值相等,x=1
cout << x << endl;
x = (y & z); //y和z按位与,y:0011,z:0011,x值为3
cout << x << endl;
x = (y && z);//y和z进行与运算,y为真z为真,返回布尔值1,x的值
//为1
cout << x << endl;
y = 4;
x = (y | z);//y和z按位或,y:0100,z:0011,x:0111,x值为7
cout << x << endl;
x = (y || z); //y和z或运算,(y||z)为真返回布尔值为1,x值为1
cout << x << endl;
return 0;
}
3.int func(int x)
{
int count = 0;
while(x)
{
count++;
x = x&(x-1);
}
return count;
}
函数func功能是将形参x转换为二进制后,包含1的数量
二、i++
#include<stdio.h>
main()
{
int b = 3;
int arr[] = {6,7,8,9,10};
Sint *ptr = arr;//ptr指向第一个元素6
*(ptr++) += 123; //*ptr = *ptr+123;ptr++,此时第一个元素129,ptr
//指向第二个元素7
printf(“%d,%d\n”,*ptr,*(++ptr));//从右到左运算,第一个是(++ptr),也就是ptr++,*ptr = 8,此时ptr指向第三个元素8,所以全部为8
}
三、类型转换
#inlcude<stdio.h>
int main()
{
unsigned int a = 0xfffffff7;
unsigned char i = (unsigned char)a;
char *b = (char *)&a;
printf(“%08x, %08x”,i,*b);
}
在X86系列的机器中,数据存储是“小端存储”,即低位存放在低地址单元,高位存放在高地址单元。
char *b = (char *)&a;&a可以认为是个指向unsigned int类型数据的指针,(char *)&a则把&a强制转换成char *类型的指针,这时会发生截断。截断后,指针b只指向0xf7这个数据。因为bs是char *,是有符号数,所以打印出来是fffffff7
四、运算符问题
1.#include<iostream>
using namespace std;
int main()
{
unsigned char a = 0xA5;
unsigned char b = ~a>>4+1;
printf(“b = %d\n”,b);
return 0;
}
类型转换问题:unsigned char b = ~a>>4+1;在计算这个表达式的时候,编译器会先把a和4的值转换成int类型(即所谓整数提升)后再进行计算,当计算结果出来后,再把结果转换成unsigned char 赋值给b。
运算符的优先级问题:因为“~”的优先级高于“>>”和“+”,所以本题的过程是这样的:先对1010 0101取反0101 1010;再右移,因为“+”运算符的优先级高于“>>”,所以直接右移5位,结果是0000 0010.
~a操作时,会对a进行整型提升,a是无符号的,提升时左边补0(一般机器32为位,char是8位,左边24个1;16位int则左边补8个0),取反后左边为1,右移就把左边的1都移到右边,再按照无符号读取,才有250这个结果。
2.用一个表达式,判断一个数X是否是2^N次方,不可用循环语句
解析:2 4 8 16这样的数转化成二进制是10,100,1000,10000.如果X-1后与X做运算,答案若是0,则X为2^N次方
答案:!(X&(X-1))
3.int f(int x,int y)
{
return (x&y)+((x^y)>>1) //求两数的平均值
}
五、C和C++问题
1.在C++程序中调用被C编译器编译后的函数,为什么要加extern “C”?
答:C++语言支持函数重载,C语言不支持函数重载。函数被C++编译后在库中的名字与C语言不同。假设某个函数的原型为void foo(int x,int y).该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。
C++提供了C连接交换指定符号extern “C”解决名字匹配问题
2.头文件中的ifndef/define/endif是干什么用的?
答:头文件中的ifndef/define/endif是条件编译的一种,除了头文件被防止重复引用(整体),还可以防止重复定义(变量,宏或者结构)。