Chinaunix首页 | 论坛 | 博客
  • 博客访问: 51848
  • 博文数量: 35
  • 博客积分: 2500
  • 博客等级: 少校
  • 技术积分: 315
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-10 10:44
文章存档

2011年(1)

2008年(34)

我的朋友
最近访客

分类: C/C++

2008-12-10 11:31:48

基础2.类型,运算符与表达式
1.数据类型及长度
char 字符型,占用一个字节,可以存放本地字符集中的一个字符,
int 整型,通常反映了所有机器中整数的最自然长度
float 单精度浮点型
double 双精度浮点型
short类型通常为16位,long类型通常为32位,int类型可以为16位或32位。
short <= int <= long
16 <= short <= int <= 32 <= long
 
printf("signed char min = %d\n", -(char)((unsigned char) ~0 >> 1));
printf("signed char max = %d\n", (char)((unsigned char) ~0 >> 1));
printf("unsigned char max = %d\n", ((unsigned char) ~0));
printf("unsigned short max = %d\n", ((unsigned short) ~0));
1)先把数字0的各个二进制位全部转换为1: ~0
2)然后,将结果值转换为unsigned char类型:(unsigned char) ~0
3)再把这个unsigned char类型值右移一位以清除符号位:(unsigned char) ~0 >> 1
4)最后把她转换为char类型:(char)((unsigned char) ~0 >> 1)
这一系列操作的最终结果就得到了signed类型字符的最大值
 
2.常量
  没有后缀的浮点数常量为double类型。后缀f或F表示float类型,而后缀l或L则表示long double类型
常量表达式是仅仅只包含常量的表达式。这种表达式在编译时求值,而不在运行时求值。它可以出现在常量可以出现的任何位置,例如:
#define MAXLINE 1000
char line[MAXLINE+1];
 
我们下面设计一个strlen函数的一个版本:
int strlen(char s[])
{
   int i;
   i = 0;
   whlie (s[i] != '\0')
      ++i;
   return i;
}
标准库函数strlen(s)可以返回字符串参数s的长度,但长度不包括末尾的'\0'
"hello," "world" 等价于 "hello,world"
我们应该搞清楚字符常量与仅包含一个字符的字符串之间的区别:'x'与"x"是不同的。
前者是一个整数,其值是字母x在机器字符集中对应的数值(内部表示值);
后者是一个包含一个字符(即字母x)以及一个结束符'\0'的字符数组
 
enum boolean {NO, YES};
  枚举是一个常量整型值的列表,在没有显式说明的情况下,enum类型中第一个枚举名的值为0,第二个为1,依此类推。
  枚举为建立常量值与名字之间的关联提供了一种便利的方式。相对于#define语句来说,它的优势在于常量值可以自动生成。尽管可以声明enum类型的变量,但编译器不检查这种类型的变量中存储的值是否为该枚举的有效值。不过,枚举变量提供这种检查,因此枚举比#define更具优势。此外,调试程序可以以符号形式打印出枚举变量的值。
 
3.关于声明
  所有变量都必须先声明后使用,如果变量不是自动变量,则只能进行一次初始化操作,从概念上讲,应该是在程序开始执行之前进行,并且初始化表达式必须为常量表达式。每次进入函数或程序块时,显式初始化的自动变量都将被初始化一次,其初始化表达式可以是任何表达式。在默认情况下,外部变量与静态变量将被初始化为0。未经显式初始化的自动变量的值为未定义值(即无效值)。
  任何变量的声明都可以使用const限定符限定。该限定符指定变量的值不能被修改。对数组而言,const限定符指定数组所有元素的值都不能被修改:
const double e = 2.71828
const char msg[] = "warning: ";
const限定符也可配合数组参数使用,它表明函数不能修改数组元素的值:
int strlen(const char[]);
如果试图修改const限定符限定的值,其结果取决于具体的实现。
 
4.算术运算符
  取模运算符%不能应用于float或double类型。在有负操作数的情况下,整数除法截取的方向以及取模运算结果的符号取决于具体机器的实现,这和处理上溢或下溢的情况是一样的。

原来的for循环语句:
for (i=0; i与之等价的循环语句:
enum loop = { NO, YES };
enum loop okloop = YES;
i = 0;
while (okloop == YES)
if (i >= lim-1)
    okloop = NO;
else if((c = getchar()) == '\n')
    okloop = NO;
else if(c == EOF)
    okloop = NO;
else {  
     s[i] = c;
     ++i;
}
 
5.类型转换
  将字符类型转换为整型时,我们需要注意一点。C语言没有指定char类型的变量是无符的值时,其结果有没有可能为负整数?对于不同的机器,其结果也不同,这反映了不同机器结构之间的区别。在某些机器中,如果char类型值的最左一位为1,则转换为负整数(进行"符号扩展")。而在另一些机器中,把char类型值转换为int类型时,在char类型值的左边添加0,这样导致的转换结果值总是正值。
  为了保证程序的可移植性,如果要在char类型的变量中存储非字符数据,最好指定signed或unsigned限定符。
1L = signed long
1U = unsigned int
1UL = unsigned long
首先,-1L < 1U,这是因为unsigned int类型的1U将被提升为signed long类型;
但是,1UL < -1L,这是因为-1L将被提升为unsigned long类型,因而成为一个比较大的正数
由于函数调用的参数是表达式,所以在把参数传递给函数时也可能进行类型转换。在没有函数原型的情况下,char与short类型都将转换为int类型,float类型将转换为double类型。因此,即使调用函数的参数为char或float类型,我们也把函数参数声明为int或double类型。
 
6.自增运算符
/* 将字符串t连接到字符串s的尾部;s必须有足够大的空间 */
void strcat(char s[], char t[])
{
   int i,j;
   i = j = 0;
   while (s[i] != '\n')
       i++;
   while ((s[i++] = t[j++]) != '\0')
       ;
}
 
7.按位运算符
x = x & ~077
  注意,表达式x&~077与机器字长无关,它比形式为 x&0177700的表达式要好,因为后者假定x是16位的数值。这种可移植的形式并没有增加额外开销,因为~077是常量表达式,可以在编译时求值。
& | ^ << >> ~共六个符号按照从左至右的顺序执行.
 
  编写一个函数setbits(x, p, n, y),该函数返回对x执行下列操作后的结果值:将x中从第p位开始的n个(二进制)位设置为y中最右边n位的值,x的其余各位保持不变。
unsigned setbits(unsigned x, int p, int n, unsigned y)
{
    return x & ~( ~(~0 << n) << (p+1-n) ) | (y & ~( ~0 << n)) << (p+1-n);
}
 
8.赋值运算符与表达式
下面的函数bitcount统计其整型参数的值为1的二进制位的个数
int bitcount(unsigned x)
{
   int b;
   for (b = 0; x != 0; x >>= 1)
       if (x & 01)
           b++;
   return b;
}
这里将x声明为无符号类型是为了保证将x右移时,无论该程序在什么机器上运行,左边空出的位都用0(而
不是符号位)填补。
表达式i+=2比i=i+2更自然
 
9.条件表达式
将大写字母转换为小写字母的函数lower
int lower(int c)
{
    return c >= 'A' && c <= 'Z' ? c + 'a' - 'A' : c;
}
阅读(346) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~