第二章:类型、运算符与表达式

第二章:类型、运算符与表达式

变量和常量是程序处理的两种基本数据对象。声明语句说明变量的名字和类型,也可以指定变量的初值。运算符指定将要进行的操作。表达式则把变量与常量组合起来生成新的值。对象的类型决定该对象可取值的集合以及可以对该对象执行的操作。

2.1变量名

变量名:由字母和数字组成的序列,但其第一个字符必须为 字母。下划线“_”也被看作字母。变量名一般为小写字母,而符号常量则用大写字母。

2.2数据类型及长度

char  字符型,占用一个字节,可以存放本地字符集中的一个字符。
int   整型,通常反映了所用机器中整数的最自然长度
float   单精度浮点型
double 双精度浮点型
限定符:short与long用于限定整型;signed与unsigned可用于限定char型或任何整型。

2.3常量

  • 整型数除了用十进制表示外还可以用八进制和十六进制表示,带前缀o的整型常量表示八进制形式;带前缀ox/OX,表示十六进制形式。
  • 一个字符常量就是一个整数,如‘\n’、‘\t’,字符在机器字符集中的数值就是字符常量的值。
  • 某些字符可以通过转义字符序列表示为字符和字符串常量;所有转义字符序列都只表示一个字符。
  • 整数常量:类似于1234的整数,long类型的常量以l/L结尾,如123456l,无符号常量以u/U结尾,unsigned long则以ul/UL结尾。
  • 浮点数常量中包含一个小数点(如123.4)或一个指数(如1e-2),也可以两者都有;而没有后缀的浮点数常量为double类型。
  • 字符常量’\0’表示值为0的字符,用此代替0以强调某些表达式的字符属性。
  • 常量表达式是仅仅包含常量的表达式,在编译时求值,而不在运行时求值。它可以出现在常量可以出现的任何位置,如`
#define MAXLINE 1000
char line [MAXLINE+1];

#define LEAP 1
int days[31+28+31+30+31+30+31+31+30+31+30+31];

-字符串常量也叫字符串字面值,是用双引号括起来的0个或多个字符组成的字符序列;

"I am a strring"

" "/*空字符串*/

从技术角度来看,字符串常量就是字符数组,字符串内部使用’\0’结尾,因此,存储字符串的物理存储单元数比在双引号中的字符数多一个。

下面我们来看几个函数:

-strlen函数:将返回字符串s的长度

int strlen(char s[])
{
    int i;
    i = 0;
    while ( s[i] != '\0' )
        ++i;
    return i;
}

枚举常量:枚举是一个常量整型值的列表。

enum boolean { NO, YES};
enum escapes { BELL = '\a', BACKSPACE = '\b', TAB = '\t', 
                            NEWLINE = '\n', VTAB = '\v', RETURN = '\r' };

enum month {JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC};

枚举为建立常量值与名字之间的关联提供了一种便利的方式,相对#define来说,它的优势在于常量值可以自动生成。

2.4声明

所有变量都必须先声明后使用

int lower, upper, step;
char c, line [100];
int lower;
int upper;
int step;
char c;
char line [100];

以上两种代码是等价的,后一种书写方式比较占用空间,但是便于向各声明语句添加注释。
-任何变量的声明都可以用const限定符限定,该限定符指定变量的值不能被修改;

const double e = 2.718281845905;
const char msg [] = "warning: ";

2.5算术运算符

  • 二元运算符 + - * / %(取余)
  • 一元运算符 +(正) -(负)
  • 整数除法会截断结果中小数部分。

2.6关系运算符与逻辑运算符

  • 关系运算符 > >= < <= ==(等于) !=(不等于)
  • 逻辑运算符 &&(逻辑与) ||(逻辑或) !(非)
  • 对于&&,当左边结果false时,不再做右边运算;
  • 对于||,当左边结果true时,不再做右边运算;
  • 对于!,作用是将非零操作数转为0,将0转化为1;
    三者的优先级:算术>关系>逻辑

2.7类型转换

自动转换是指把“比较窄”的转化为“比较宽”的操作数,并且不丢失信息的转换。

  • atoi函数:将字符串s转换为相应的整型数
int atoi ( char s[] )
{
    int i, n;
    n = 0;
    for ( i = 0; s[i] >= '0' && s[i] <= '9'; ++i)
           n = 10 * n + ( s[i] - '0');/*能够计算出s[i]中存储的字符所对应的数值,这是因为'0','1'等在字符集中对应的数值是一个连续的递增序列*/
    return n;
}

lower函数:把字符c转换为小写形式

int lower (int c)
{
	if (c >= 'A' && c <= 'z')
		return c + 'a' - 'A';
	else
		return c;
}

由于char类型就是较小的整型,因此在算术表达式中可以自由使用char类型的变量,这就为实现某些字符转换提供了很大的活性。

自动转换规则
  • 若其中一个操作数为long double类型,则将另一个也转换为long double类型;
  • 若其中一个操作数为double类型,则将另一个也转换为 double类型;
  • 若其中一个操作数为float类型,则将另一个也转换为float类型;
  • 将char 与short类型的操作数转换为int类型;
  • 若其中一个操作数为long 类型,则将另一个也转换为long 类型;
  • 表达式中float类型的操作数不会自动转换为double类型;
    赋值时也要进行类型转换,赋值运算符右边值要换成左边变量类型,左边变量类型即结果类型,当把较长整数转换为较短整数或char类型时,超出的高位部分将被丢弃。
强制转换
  • (类型名)(表达式)

在这里插入代码片

sqrt (  (double) n)
  • 准确含义:表达式首先将被赋值给类型名指定的某个变量,然后再利用该变量替换上述整条语句。
  • 注意:强制类型转换只是生成一个指定类型n的值,n本身并没有改变。
    标准库函数中包含一个可移植的实现伪随机数发生器的函数rand及一个初始化种子数的srand函数。

rand函数:返回取值为0-32767的伪随机数

unsigned long int next = 1;
int rand(void)
{
	next = next * 1103515245 + 12345;
	return (unsigned int)(next / 65536) % 32768;
}

srand函数:为rand()设置种子数

void srand (unsigned int seed)
{
	next = seed;
}

2.8自增/自减运算符

  • ++ –
  • 前缀和后缀效果都是将变量加1或减1;但前缀是先加减1,再使用变量(加减1 后的值);而后缀则是先使用变量再加减1;
if (c == '\n')
	++nl;
if (c == '\n')
	nl++;

此处两者的效果都是一样的;
但是

x = n++;
x = ++n;

两者却不一样

  • squeeze函数:从字符串中删除所有出现的字符c
void squeeze (char s[], int c)
{
	int i, j;
	for (i = j = 0; s[j] != '\0'; i++)
		if (s[j] != c)/*不是c的字符,该函数就把它拷贝到数组下标为j的位置,随后才将j的值增加1*/
			s[j++] = s[i];
	s[j] = '\0';
}
  • strcat函数:将字符串t连接到字符串s的尾部;s必须有足够大的空间
void strcat (char s[], char t[])
{
	int i, j;
	i = j = 0;
	while (s[i] != '\0')/*判断是否为s的尾部*/
		i++;
	while ((s[i++] = t[j++] !='\0'))/*拷贝t*/
		;
}

2.9位运算符

  • &按位与 0&0=0;0&1=1;1&0=0;1&1=1;1&x=x;0&x=0;(与零为零)
  • |按位或 0|0=0;0|1=1;1|0=1;1|1=1;1|x=1;0|x=0;(或一为一)
  • ^按位异或 0 ^ 0=0;0 ^ 1=1;1 ^ 0=1;1 ^1=0;(同零异一)
  • <<按位左移 >>按位右移
    移位运算符将左操作数左移或右移,移动右操作数(右操作数的值)位,空位用0填补(左移补右边,右移补左边)
  • ~按位取反 ~0=1; ~1=0;

2.10赋值运算符

+= -= /= *=
函数getbits(x,p,n),它返回x中从右边第p位开始向右数n位的字段,假定最右边的一位为第0位,n与p都是合理的值。

unsigned getbits (unsigned x,int p, int n)
{
	return (x >> (p+1-n) & ~(~0 << n));/*表达式x>>(p+1-n)将期望获得字段移位到字符的最右端。~0的所有位都为1,~0<<n将`0左移n位,并将右边用0填补。再用~对它进行取反*/
}

2.11条件表达式

  • ? :
  • expr1 ? expr2 : expr3(若expr1为真,则计算expr2,否则计算expr3)
if (a > b)
	z = a;
else
	z = b;

等价于

z = (a > b) ? a : b;/*z=max(a,b)*/

再来看看下面这个

for (i = 0; i < n; i++)
printf("%6d %c",a[i],(i % 10 == 9 || i == n-1) ? '\n' : ' ');
/*打印一个数组的n个元素,每行打印10个元素,每 列之间用一个空格隔开,每行用一个换行符结束*/
printf("You have %d item%s.\n",n,n == 1 ? " " : " s");
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值