C程序设计语言--第二章:类型,运算符与表达式
博客专区 > fzyz_sb 的博客 > 博客详情
C程序设计语言--第二章:类型,运算符与表达式
fzyz_sb 发表于4年前
C程序设计语言--第二章:类型,运算符与表达式
  • 发表于 4年前
  • 阅读 102
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 新注册用户 域名抢购1元起>>>   

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

2.1 变量名

名字是由字母和数字组成的序列,但第一个字符必须为字母.下划线'_'被看作是字母.

由于库例程的名字通常以下划线开头,因此变量名不要以下划线开头.变量名使用小写字母,符号常量名全部使用大写字母.

选择的变量名要能够尽量从字面上表达变量的作用,这样做不容易引起混淆.局部变量一般使用较短的变量名(尤其是循环控制变量),外部变量使用较长的名字.

2.2 数据类型及长度

C语言只提供下列几种基本数据类型:

char    字符型,占用一个字节,可以存放本地字符集中的一个字符

int        整型,通常反映了所用机器中整数的最自然长度

float    单精度浮点型

double    双精度浮点型

C语言也提供了限定符:short和long用于限定整型,类型限定符signed与unsigned可用于限定char类型或任何整型.

习题2-1:备注:这里unsigned要用%u来输出,long要用%l来修饰:


#include <stdio.h>
#include <limits.h>

int main(void)
{
	signed char schar;
	unsigned char uschar;
	signed short sshort;
	unsigned short ushort;
	signed int sint;
	unsigned int usint;
	signed long slong;
	unsigned long ulong;

	schar = 0;
	while ( schar >= 0 ){
		schar++;
	}
	printf("%d\n", schar );
	printf("%d\n", -schar - 1 );
	uschar = -1;
	printf("%u\n", uschar );

	sshort = 0;
	while ( sshort >= 0 ){
		sshort++;
	}
	printf("%d\n", sshort );
	printf("%d\n", -sshort - 1 );
	ushort = -1;
	printf("%u\n", ushort );

	sint = 0;
	while ( sint >= 0 ){
		sint++;
	}
	printf("%d\n", sint );
	printf("%d\n", sint - 1 );
	usint = -1;
	printf("%u\n", usint );

	slong = 0;
	while ( slong >= 0 ){
		slong++;
	}
	printf("%d\n", slong );
	printf("%d\n", slong - 1 );
	ulong = -1;
	printf("%lu\n", ulong );

	printf("\n----------------------\n");

	printf("%d\n", SCHAR_MIN );
	printf("%d\n", SCHAR_MAX );
	printf("%u\n", UCHAR_MAX );

	printf("%d\n", SHRT_MIN );
	printf("%d\n", SHRT_MAX );
	printf("%u\n", USHRT_MAX );

	printf("%d\n", INT_MIN );
	printf("%d\n", INT_MAX );
	printf("%u\n", UINT_MAX );

	printf("%d\n", LONG_MIN );
	printf("%d\n", LONG_MAX );
	printf("%lu\n", ULONG_MAX );

	return 0;
}
程序输出:


2.3 常量

一个字符常量是一个整数,书写时将一个字符括在单引号中,如'x'.

某些字符可以通过转义字符序列(如换行符\n)表示为字符和字符串常量(转移字符怎么表示字符串常量??)

转移字符序列看起来像两个字符,但只表示一个字符.另外,我们可以用'\000'表示任意的字节大小的位模式,其中000代表1~3个八进制数字.也可以使用'xhh'来表示,而hh代表1~2个十六进制数字.


#define VTAB '\013'    /*ASCII纵向制表符*/
#define BELL '\007'    /*ASCII响铃符*/

当然,也可以写成十六进制:

#define VTAB '\xb'    /*ASCII纵向制表符*/
#define BELL '\x7'    /*ASCII响铃符*/
C语言中全部转移字符如下:
\a		响铃符
\b		回退符
\f		换页符
\n		换行符
\r		回车符
\t		横向制表符
\v		纵向制表符
\\		反斜杠
\?		问号
\'		单引号
\"		双引号
\000	        八进制
\xhh	        十六进制
字符常量'\0'表示值为0的字符,也就是空字符(null).我们通常用'\0'的形式代替0,以强调某些表达式的字符属性,但其数字值为0.

常量表达式是仅仅只包含常量的表达式.这种表达式在编译时求值(如宏定义).

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

枚举常量是另外一种类型的常量.枚举是一个常量整型值的列表,例如:

enum boolean { NO, YES };
在没有显式说明的情况下,enum类型中第一个枚举名的值为0,第二个为1,依此类推.

枚举为建立常量值与名字之间的关联提供了一种便利的方式.相对于#define语句来说,它的优势在于常量可以自动生成.尽管可以声明enum类型的变量,但编译器不检查这种类型的变量中存储的值是否为该枚举的有效值.不过,枚举变量提供这种检查,因此枚举比#define更有优势.此外,调试程序可以以符号形式打印出枚举变量的值.

2.4 声明

所有变量都必须先声明后使用.尽管某些变量可以通过上下文隐式声明.一个声明指定一个变量类型,后面所带的变量表可以包含一个或多个该类型的变量.

还可以在声明的同时对变量进行初始化.默认情况下,外部变量与静态变量将初始化为0.未经显示初始化的自动变量的值为未定义值(即无效值).

任何变量的声明都可以使用const限定符限定.该限定符指定变量的值不能被修改.对数组而言,const限定符指定数组所有元素的值都不能被修改.

for ( i = 0; i < lim - 1; i++ ){
	if ( ( c = getchar() ) != '\n' ){
		if ( c != EOF ){
			s[ i ] = c;
		}
	}
}
2.7 类型转换

习题2-3:

#include <stdio.h>

int htoi( char *s )
{
	int num = 0;
	int tempNum = 0;
	if ( '0' == s[ 0 ]  && ( 'x' == s[ 1 ] || 'X' == s[ 1 ] ) ){
		s += 2;
	}
	while ( '\0' != *s ){
		if ( *s >= 'a' && *s <= 'f' ){
			tempNum = *s - 'a' + 10;
		}
		else if ( *s >= 'A' && *s <= 'F' ){
			tempNum = *s - 'A' + 10;
		}
		else{
			tempNum = *s - '0';
		}
		num = num * 16 + tempNum;
		s++;
	}

	return num;
}

int main(void)
{
	printf("%d\n", htoi( "0x1b2" ) );
	printf("%d\n", htoi( "0xff" ) );
	printf("%d\n", htoi( "0x1abc" ) );

	return 0;
}
程序输出:


2.8 自增运算符与自减运算发

习题2-4:

#include <stdio.h>

void squeeze( char *s1, char *s2 )
{
	char *temp = s1;		//用于存储每次修改的值
	char *newstr = temp;	//用于初始化修改后的值
	while ( '\0' != *s2 ){
		s1 = newstr;
		temp = newstr;
		while ( '\0' != *s1 ){
			if ( *s1 != *s2 ){
				*temp++ = *s1++;
			}
			else{
				s1++;
			}
		}
		*temp = '\0';
		s2++;
	}
}

int main(void)
{
	char s1[] = "hello world i love this world";
	char s2[] = "els";
	squeeze( s1, s2 );
	printf("%s\n", s1 );

	return 0;
}
程序输出:

习题2-5:

#include <stdio.h>

int any( char *s1, char *s2 )
{
	char *temp = s1;
	char *newStr = s1;
	while ( '\0' != *s2 ){
		s1 = newStr;
		while ( '\0' != *s1 ){
			if ( *s2 == *s1 ){
				return s1 - temp;
			}
			s1++;
		}
		s2++;
	}

	return -1;
}

int main(void)
{
	printf("%d\n", any( "hello world", "owd" ) );

	return 0;
}
程序输出:

习题2-6:

#include <stdio.h>

unsigned int setbits( int x, int p, int n, int y )
{
	return ( ( x >> p ) & ( ~( ~0 << n ) ) | ( ( y >> n ) << n ) );
}

int main(void)
{
	printf("%d\n", setbits( 94, 3, 4, 164 ) );

	return 0;
}
程序输出:

习题2-7:

#include <stdio.h>

unsigned int invert( int x, int p, int n )
{
	return ( x >> ( p + n ) << ( p + n ) ) + ( ( ~( x >> p ) & ~( ~0 << n ) ) << p ) + ( x & ( ~( ~0 << p ) ) ); 
}

int main(void)
{
	printf("%d\n", invert( 94, 3, 4 ) );

	return 0;
}
程序输出:

2-8:

#include <stdio.h>

unsigned int rightrot( int x, int n )
{
	int tempNum = x;
	int numOfBit = 0;
	while ( tempNum ){
		numOfBit++;
		tempNum /= 2;
	}
	while ( n-- ){
		x = ( ( x & ~( 1 << ( numOfBit - 1 ) ) ) << 1 ) + ( x >> ( numOfBit - 1 ) );
	}

	return x;
}

int main(void)
{
	printf("%d\n", rightrot( 94, 4 ) );

	return 0;
}
程序输出:

习题2-9:

#include <stdio.h>

int bitcount( unsigned x )
{
	int b;
	for ( b = 0; x != 0; x &= x - 1 ){
		b++;
	}

	return b;
}

int main(void)
{
	printf("%d\n", bitcount( 94 ) );

	return 0;
}
程序输出:

举例来说,如果x = 1011,则关键不是在x & ( x - 1 )中x目前的值(1011),因为谁都明白x=1010,减少了一个1,关键是在对于末尾为0的时候,如何进行计数!

当x为1010的时候,x & ( x - 1 )的操作会使最右边的1消失(试想一下,x为1010,x-1为1001,在这种情况下进行&操作,是不是将最右边的1置零了呢?).于是就达到了计算1的个数的目的.

习题2-10:

#include <stdio.h>

void myLower( char *str )
{
	while ( '\0' != *str ){
		*str = ( *str >= 'A' && *str <= 'Z' ) ? ( *str + 'a' - 'A' ) : *str;
		str++;
	}
}

int main(void)
{
	char str[] = "HElLo, WoRlD";
	myLower( str );
	printf("%s\n", str );

	return 0;
}
程序输出:

2.12 运算符优先级与求值次序

x = f() + g();
f()可以在g()之前计算,也可以在g()之后计算.因此,如果函数f或g改变了另一个函数所使用的变量,那么x的结果可能会依赖于这两个函数的计算顺序.

函数调用,嵌套赋值语句,自增与自减运算符都有可能产生"副作用"---在对表达式求值的同时,修改了某些变量的值.

共有 人打赏支持
粉丝 360
博文 209
码字总数 447144
×
fzyz_sb
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: