复习(1)

1、把int和long两个类型的字节大小说错,在32位、64位系统下的32位和64位编译器下,数据类型和指针所占内存字节数是多少?
答:32位平台下结果:
sizeof(char)= 1
sizeof(short) = 2
sizeof(float) = 4
sizeof(double) = 8
sizeof(int) = 4
sizeof(long) = 4
sizeof(long long) = 8
sizeof(void *) = 4

64为平台下结果:
sizeof(char) = 1
sizeof(short) = 2
sizeof(float) = 4
sizeof(double) = 8
sizeof(int) = 4
sizeof(long) = 8
sizeof(long long) = 8
sizeof(void *) = 8
32位编译器下,数据类型long的字节数为4,指针所占字节数为4.
64位编译器下,数据类型long的字节数为8,指针所占字节数为8.

2、搞不清楚字符编码,尤其是项目中最常用的ASCII、UTF-16、UTF-8编码的区别。
答:归纳:
在这里插入图片描述
具体解释:
最早只有127个字母被编码到计算机里,也就是大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码,比如大写字母A的编码是65,小写字母z的编码是122。
但是要处理中文显然一个字节是不够的,至少需要两个字节,而且还不能和ASCII编码冲突,所以,中国制定了GB2312编码,用来把中文编进去。
你可以想得到的是,全世界有上百种语言,日本把日文编到Shift_JIS里,韩国把韩文编到Euc-kr里,各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。
因此,Unicode应运而生。Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。
Unicode标准也在不断发展,但最常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。现代操作系统和大多数编程语言都直接支持Unicode。
新的问题又出现了:如果统一成Unicode编码,乱码问题从此消失了。但是,如果你写的文本基本上全部是英文的话,用Unicode编码比ASCII编码需要多一倍的存储空间,在存储和传输上就十分不划算。
所以,本着节约的精神,又出现了把Unicode编码转化为“可变长编码”的UTF-8编码。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间。
UTF-8编码有一个额外的好处,就是ASCII编码实际上可以被看成是UTF-8编码的一部分,所以,大量只支持ASCII编码的历史遗留软件可以在UTF-8编码下继续工作。
Unicode 是容纳世界所有文字符号的国际标准编码,使用四个字节为每个字符编码。
UTF 是英文 Unicode Transformation Format 的缩写,意为把 Unicode 字符转换为某种格式。UTF 系列编码方案(UTF-8、UTF-16、UTF-32)均是由 Unicode 编码方案衍变而来,以适应不同的数据存储或传递,它们都可以完全表示 Unicode 标准中的所有字符。目前,这些衍变方案中 UTF-8 被广泛使用,而 UTF-16 和 UTF-32 则很少被使用。
UTF-8 使用一至四个字节为每个字符编码,其中大部分汉字采用三个字节编码,少量不常用汉字采用四个字节编码。因为 UTF-8 是可变长度的编码方式,相对于 Unicode 编码可以减少存储占用的空间,所以被广泛使用。
UTF-16 使用二或四个字节为每个字符编码,其中大部分汉字采用两个字节编码,少量不常用汉字采用四个字节编码。UTF-16 编码有大尾序和小尾序之别,即 UTF-16BE 和 UTF-16LE,在编码前会放置一个 U+FEFF 或 U+FFFE(UTF-16BE 以 FEFF 代表,UTF-16LE 以 FFFE 代表),其中 U+FEFF 字符在 Unicode 中代表的意义是 ZERO WIDTH NO-BREAK SPACE,顾名思义,它是个没有宽度也没有断字的空白。
UTF-32 使用四个字节为每个字符编码,使得 UTF-32 占用空间通常会是其它编码的二到四倍。UTF-32 与 UTF-16 一样有大尾序和小尾序之别,编码前会放置 U+0000FEFF 或 U+0000FFFE 以区分。

3、位运算忘了,分不清算术位移和逻辑位移,也不知道c编译器采用的是哪一种
答:C语言提供了六种位运算符:
&(按位与)、|(按位或)、^(按位异或)、~(按位取反)、<<(按位左移,相当于*2),>>(按位右移,相当于/2,正数高位补0,负数由计算机决定)
循环左移k次 (x<<k) | (x >> (32-k)),
循环右移k次 (x>>k) | (x << (32-k))
(1)按位与运算
按位与运算符"&"是双目运算符。其功能是参与运算的两数各对应的二进位相与。只有对应的两个二进位均为1时,结果位才为1,否则为0。参与运算的数以补码方式出现。
按位与运算通常用来对某些位清0或保留某些位。例如把a 的高八位清 0 ,保留低八位,可作a&255运算(255 的二进制数为0000000011111111)
(2)按位或运算
按位或运算符“|”是双目运算符。其功能是参与运算的两数各对应的二进位相或。只要对应的二个二进位有一个为1时,结果位就为1。参与运算的两个数均以补码出现。
(3)按位异或运算
按位异或运算符“^”是双目运算符。其功能是参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。参与运算数仍以补码出现。
(4)求反运算
求反运算符~为单目运算符,具有右结合性。其功能是对参与运算的数的各二进位按位求反。
(5)左移运算
左移运算符“<<”是双目运算符。其功能把“<< ”左边的运算数的各二进位全部左移若干位,由“<<”右边的数指定移动的位数,高位丢弃,低位补0
(6)右移运算
右移运算符“>>”是双目运算符。其功能是把“>>”左边的运算数的各二进位全部右移若干位,“>>”右边的数指定移动的位数。
注意:对于有符号数,在右移时,符号位将随同移动。当为正数时,最高位补0,而为负数时,符号位为1,最高位是补0或是补1 取决于编译系统的规定。Turbo C和很多系统规定为补1。
运用:
(1)交换两个数(字符),不用第三个变量就可以交换两个变量的值了:
用异或^,原理:两次异或能还原,即a = (a^b) ^ b

(2)判断一个数是不是2的幂次:
原理:2的幂次的二进制表示中只有一位是1,其他位为0
x = x&(x-1)是让x的二进制码最右侧的1置为0,如果结果为0就表示原先x只有1位是1,其他位为0
inline bool is2pow(int x) { return (x&(x-1)==0 && (x!=0)); }
inline bool is2pow(int x) { return ( (x&-x)==x ); }

(3)求一个整数有多少位是0:
原理同上。用x&(x-1)

 int  count = 0;
while(x)
{
	++count;
	x &= (x-1);
}

(4)二进制快速求幂:

long pow(int x, unsigned int n){
     long p = 1;
     while (n){
         if (n & 1) p *= x;
         x *= x;
         n >>= 1;
     }
     return p;
 }

(5)判断奇偶数:
原理:奇数最后一位为1,偶数为0
inline bool odd(int x) { return x&1; }
inline bool even(int x) {return !(x&1); }
n%2 = n&1
n%4 = n&3
n%8 = n&7
……

(6)求x绝对值:
原理:x为正数时不做改变,为负数时取反加1
x为正数时y = 0 = 0000 0000 0000 0000
x为负数时y = -1 = 1111 1111 1111 1111
跟0异或是本身,跟1异或是取反
inline int abs(int x){
int y = x >> 31;
return ( x^y-y);
}

(7)对2的幂次取模:
原理:x&y取出x和y二进制位1的所有位。x^y>>1取出x,y只有一个二进制位1的并除以2
return (x&y) + (x^y)>>1);
不用位运算时注意 (x+y)/2,有可能会溢出。
x向上取整到y,其中y=2^n (字节对齐用):
#define rund(x,y) ( ((x)+(y)-1)&~((y)-1) )

(8)其他:
只有第k位为1的数 1 << (k-1)
后k位为均为1的数 (1<<k)-1
x 的第k+1位 x >> k &1
x的第k+1位置1: x >> k |(1 << k)
x的第k+1位置0: x >> k &~(1 << k)
注意:左移1位再右移1位不一定时原先的值

算术位移与逻辑位移:
逻辑移位:移位所缺少的数字用“0”来填充
算术移位:移位所缺少的数字用符号位来填充
在C/C++中,整数分为有符号整数和无符号整数两种

  • 1 - 对于无符号数,采用逻辑移位,不论左移右移都用“0”填充;
  • 2 - 对于有符号数,分左移和右移两种情况
    • 2a - 若为左移,则属于逻辑运算,补“0”
    • 2b - 若为右移,则属于算术运算,补“符号位”
      int main()
      {
      int a = 1;
      int b = 32;
      printf("%d,%d",a << b,1 << 32);
      return 0;
      }
      结果为1,0
      对于常量,由于左移的位数大于了31位,所以结果为0
      而对于变量,如果移位的位数 b 大于了该类型的大小 sz ,则先用b对sz取模,即 b = b % sz,然后再进行移位运算

4、for和while循环有什么区别?(汇编实现上),Linux上看源代码汇编的命令是什么?
答:区别:控制条件语句的变量,在for循环结束后,就不可以被访问了,而while循环还可以访问,如果你继续想使用该变量,则可以使用while循环,否则推荐使用for循环,原因是for循环结束,该变量就从内存中消失,能够提高内存的使用效率。
Linux上看源代码汇编的命令是:首先编译debug版本,然后dump -d demo.

5、switch怎么实现的?什么时候用switch比if else高效?(汇编实现上)
答:switch的实现:
switch(表达式)
{
case 常量表达式1:语句1;

case 常量表达式2:语句2;
default:语句;
}
switch…case…执行效率高,属于典型的以空间换时间。也就是说,(套用算法的行话)以提高空间复杂度为代价降低了时间复杂度。
在选择分支较多时,选用switch…case结构会提高程序的效率,但switch不足的地方在于只能处理字符或者数字类型的变量,if…else结构更加灵活一些,if…else结构可以用于判断表达式是否成立,比如if(a+b>c),if…else的应用范围更广,switch…case结构在某些情况下可以替代if…else结构。

6、C的默认类型转换都有哪些?
答:
(1).当出现在表达式里时,有符号和无符号的char和short类型都会被自动转换为INT类型。FLOAT类型也会自动转换为DOUBLE类型。
(2).在包含两种数据类型的任何运算里,两个值都被转换成两种类型里面的较高级别。(算术运算式中 ,低类型能够转换为高类型)
(3).类型级别从高到低的顺序是long double, double, float, unsigned long long, long long, long, unsigned int 和 int.
(4).在赋值语句里,计算的最后结果将被转换成要被赋予值的那个变量的类型。(赋值表达式中 ,右边表达式的值自动隐式转换为左边变量的类型,并赋值给他)
(5).做为参数传递的时候,char 和 short 会被转换int, float会被转换成double。(函数调用中参数传递时 ,系统隐式地将 实参转换为形参的类型后,赋给形参。)
(6)函数有返回值时 ,系统将隐式地将返回表达式类型转换为返回值类型,赋值给调用函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值