[原创]C99基础教材(二、数据和C)
原创作者:EvilKnight (奇奇)信息来源:邪恶八进制信息安全团队([url]www.eviloctal.com[/url])
第二章 数据和c
2.1 变量与常量
在讲数据类型之前我们来学习一下什么是常量、什么是变量,老谭的书上解释如下:其值可以改变的量称为变量,其值不能被改变的量称为常量,这是他们的主要区别,变量的值可以在程序执行的过程中变化与指定,而常量不可以。
变量提供了程序可以操作的有名字的存储区,常量没有,变量有特定的类型,比如整型,浮点型等,这个我们等下会讲解.
2.2 左值与右值
1)左值:左值可以出现在赋值语句的左边或右边。
2)右值: 右值只能出能出现在赋值语句的右边,不能出现在左边.
变量是左值,右值一般是字面值,比如'a','B'等,这里要注意一下,c/c++是区分大小写的,void Creat(void),void creat(void)这二个是完全不同的二个函数哦.
2.3 变量名
变量名,即变量的标识符,可以由字母、数字、和下划线组成,且开头必须是字母或者下划线.在这里我介绍一下合名原则,好的命名原则在软件开发中是很重要的,特别是团队合作,好的命名应该是直观而容易理解的,比如人家一看到你的变量名,就知道你这个变量是用来做什么的.
2.3.1 类型名 (参照C++编码规范)
类型名中的每个英文单词的第一个字母大写,其他小写,最后以_T结尾.其中类型名包括struct、union、typedef、enum的名字.
例如:
typedef struct
{
......
}LinkList_T;
typedef short Int16_T;
这样的原因是为了防止与变量名冲突,而且后面加入_T人家一看便知是_T是类型名,_T来源于POSIX的类型命名: POSIX统一采用_t命名其类名。用_T是为了和他区分,同时避免冲突。
区分名字中各单词也可用下划线,但用大写字母会使得名字短一些。
2.3.2 变量和函数名
变量和函数名中首字母小写,其后每个单词的第一个字母大写,其他小写。
例如:
int pageCode;
2.3.3 宏、常量
这些名字要全部大写:如有多个单词,有下划线分隔。
宏指所有用宏形式定义的名字,包括常量类和函数类;常量也包括枚举中的常量成员。
例如:
#define MAX 100
typedef enum
{
UP;
DOWN;
}Symbol_T;
这个主要就是为了防止和别的变量命名冲突,宏则是为了区分于普通函数;
2.3.4 指针标识符名
建议以 p开头或以Ptr结尾;
例如:
int *pName;
主要是使读代码的人能一看到其定义就知道这是一个指针;
2.3.4 变量名前缀;
g_: 全局变量;
f_: 作用域变量(静态变量)
这个供参考作也和上面一样的,让人家看到其定义就知道其作用,同时前缀防止与局部变量名冲突.
总结:
大家在起名的名字尽量用英文比如deleteTree();creatTree();同时要本着简单明了的原则,避免使用会引起误解的词汇,名字要起得有意义;
2.4 C 数据
2.4.1 C数据类型关键字
原来的K&R关键字:int、long、short、unsigned、char、float、double;
C90关键字:signed、void;
C99新增关键字:_Bool、_Complex、_Imaginary;
int关键字提供C使用的基本的整数类型,long、short、unsigned以及ANSI附加的signed都是用于提供甚佳本类型的变种,char 关键字用于表示字母以及其他字符。float,double,long double都是用来表示带小数的数。_Bool 类型表示布尔值(true和false)._Complex和_Imaginary分别表示复数的虚数。
2.4 数据类型
2.4.1 int 类型
int(integer),整型,顾名思义,就是只能存放整数,int类型可以存放有符号的整数,可以是负数,也可以是正数,现在32的机一般都有32位,可以通过sizeof(int)测试一下,ISO/ANSI C规定int类型的最小范围是-32768~32767;
一、申明int 变量
格式是类型名 变量名;后面有一个分号,C/C++以分号才作行一条语句的结束,如果要申明多个变量的号中间以逗号隔开。
例如:
int i;
int a,b;
变量在没有初始化或者没有赋值之前是不能用的,会出错,因为不初始化或者不赋值的话他是上次使用的值。
二、变量的初始化
初始化(initialize)是在申明的时候进行的,即在要初始化变量的后面加上=和你要赋给他的值。
例如
int i = 1;
int a = 2, b = 3;
int z, x, y =5;
三、变量的赋值
赋值是在变量定义之后,比如在程序运行中,你想把i的值变成1的话可以这样写
i = 1;
要同时改变a,b为同一值时也可以这样写 a = b = 2;
四、变量的输出
我们先来看一个简单的程序
#include <stdio.h>
int main(void)
{
int i = 1;
printf ("i: %d",i);
return 0;
}
大家可以注意到这个printf()似乎和第一章里的那个不同,怎么有个%d,后面还有一个i的,下面我来细细说明,这个%d用来指示在一行中什么位置打印,它被称为格式说明符(format specifier),因为它指示printf ()应使用什么格式来显示一个数值,在实质输出中,他用后面的变量或常量来替换掉这个%d,后面还有一个i,就是用i这个变量替换掉%d,格或说明符要和后面的参数相对应,比如有二个格式控制符的话就要对应二个参数,比如i,j等...祥细的我们放在格式化输入输出里祥讲。
五、八进制与十六进制
在我们的生活中,整数一般都是十进制的,以10为基数的数,但是电脑里却有二进制、八进制、十进制、十六进制的数,这些数可以很方便的表示与计算机相关的值,不过无论他是多少进制的,在计算机中始终是以二进制的形式存储的。下面我来介绍一下八进制和十六进制
一、八进制
八进制就是以8为基数的数字,有效数字为0~7,遇八进一。
比如十进制的8转成八进制就是10;可能有人会有问题了,这样的话我们怎么样区分这个数是八进制还是十进制呢,其实区分的话很容易的,通常在表示八进制的时候前面都会加一个0(数字零).上面的例子用八进制表示就是010;
二、十六进制
十六进制就是以16为基数的数字,但是数字只有0~9呀,怎么样表示16进制呢,所以引入了字母,十六进制有效字为0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F,那如何区分呢,十六进制就在前面加0x;
比如十进制的255转成十六进制就是0xFF,在计算中存储器中的表示就是11111111.
三、八进制、十六进制的输出
#include <stdio.h>
int main(void)
{
int x = 100;
printf ( "dec: %d; octal: %o; hex: %x\n", x, x, x);
printf ( "dec: %d; octal: %#o; hex: %#x\n", x, x, x);
return 0;
}
呵呵,分析第五行的第六的区别。这个留给大家思考一下,哈哈.
3.4.2 别的整数类型
long int;
long;
short int;
short;
unsigned int;
unsigned;
unsigned long;
unsigned short;
long long;(这个是C99新增的)
可能有些人会郁闷了,不是有int型了吗?为什么还要这么多呀,麻烦死了,呵呵,想想其实不然,比如你要保存一个数,用int型的话太大,用char的话又太小,这时就可以用short型。
具体的他们在内存中占多少位,可以通过下面的代码
#include <stdio.h>
int main(void)
{
printf ( "int: %d\n",sizeof(int));
printf ( "long int: %d",sizeof(long int));
printf ( "long: %d",sizeof(long));
printf ( "short int: %d",sizeof(short int));
printf ( "short: %d",sizeof(short));
printf ( "unsigned int: %d",sizeof(unsigned int));
printf ( "unsigned: %d",sizeof(unsigned));
printf ( "unsigned long: %d",sizeof(unsigned long));
printf ( "unsigned short: %d",sizeof(unsigned short));
printf ( "long long: %d",sizeof(long long));
return 0;
}
现在说一下溢出吧..
拿个水杯来说吧,他只能装一升的水,如果你倒二升进去会怎么样呢,我们可以看到会有很多水溢出来,电脑里的溢出和这个原理也差不多,我们由上面的程序可以得知,在一台32位机上,一个int型是占32位的,4个8位的字节。他所能表示的最大数是2的32次方..现在看一个程序
#include <stdio.h>
int main(void)
{
int i = 2147483647;
printf ("%d\t%d\t%d\n",i,i+1,i+2);
return 0;
}
2147483647 -2147483648 -2147483647
结果是上面这个,就像水表这些一样,当达到了最大值,然后就回到起始点。
long和long long常量
下面在说一下这些类型,我们在前面说过了在八进制前面加一个0就表示是八进制.如果是一个long的话我们可以在数字后面加一个l或者L这里建议用大写,因为小写会让人误以为是数字1,类似long long 的话就在后面加ll或LL,前面我们还介绍了unsigned,这个可以通过添加u或U来识别,比如2147483647LLU等.
输出
现在我说一下他们的输出,刚才的程序你们可以看到,我输出一个int型的变量用%d,如果要输出unsigned int的话可以使用%u,long的话使用%ld,如果是八进制的话就用%lo,short的话可以使用h前辍,比如%hd,%ho,unsigned long类型,我们可以使用%lu,long long可以合用%lld,%llo.可以说很到闷吧,我们看一个程序吧
#include <stdio.h>
int main(void)
{
unsigned int un = 3000000000U;
short end = 200;
long big = 2147483647;
long long unsigned verybig =12345678908640LLU;
printf ( "un: %u and not %d\n", un, un);
printf ( "end: %hd and %d\n", end, end);
printf ( "big: %ld and not %hd\n", big+1, big+1);
printf ( "verybig: %llu and not %lu\n", verybig,verybig);
return 0;
}
呵呵,这个说明了用使用不正确的说明符,会造成意想不到的后果。
2.4.3 char 类型
下面我们来学习char类型,char类型主要用来存储字母标点符号之类的字符,但是他在技术实现上还是整数类型,我们知道,数据在磁盘中是以0、1的形式存储的,为了处理字符,计算机使用了一种数字编码,ASCII(American Standard Code for Informaton Interchange),用特定的整数表示特定的字符。关于char占用多大空间的问题,你们可以自己动手写个程序来判断一下。
一、申明char 类型变量及初始化
char Name;
其实这些申明都是一样的,前面是类型名空格再加变量名,申明多个的话用逗号隔开,初始化也一样,但是字符常量要用单引号括起来.
char ch = 'a'; //注意单引号是必需的
char ch = "a"; // 这样就不行了,单引号的是字符常量,双引号的是字符串常量
char ch = a; //这样也不行,这样的话把a看成是一个变量了。
char ch = 97; //可以,因为我们刚才在上面说过了,他在技术实现上还是整型.
关于字符的ASCII码你们可以上网找一找,a是97,A是65;除了可以保存字母,标点这些可打印的字符外,还可以保存一些非打印字符,比如我们前面用过的'\n',下面我列举一些转义序列及其意义。
\a:警报(ANSI C)
\b:退格
\f:换页
\n:换行
\r:回车
\t:水平制表符(相当于键盘上的TAB)
\v:垂直制表符
\\:反斜扛(\)
\':单引号(')
\":双引号(")
\?:问号(?)
\0oo:八进制的值,o代表一个八进制的数字
\xhh:十六进制的值,h代表一个十六进制的数字
2.4.4 _Bool
这是C99引进的,用于表示布尔值,即逻辑值,true(真)和false(假),因为只有二种状态,所以用一位就可以表示了,_Bool实质也是一种整数类型。
_Bool b;
可能大家会觉得这样用很麻烦吧,因为和C++有不行,不过你可以通过包含stdbool.h头文件来改变,就可以像C++一样使用bool了。具体的我过几章再讲。
2.4.5 可移植的类型:inttype.h
C99标准定义了inttype.h的头文件,这个文件用typedef定义了一系列各种类别的整数类型;
int8_t、int16_t、int32_t、int64_t、uint8_t、uint16_t、uint32_t、uint64_t名字已经很直观了,比如int8_t,表示一个8位的int型,uint64_t:表示一个64位有无符号位的int.
不过这些不是关键字哦,就和我们自己用typedef
定义的一样,所以要包含inttype.h这个头文件。
2.4.6 float、double、long double 类型
在前面我已经写过一个程序怎么样查看一个类型占多少位,这里,大家也可以自己动手试着写一个程序,看看float、double、long double占多少位。
一、声明
还是一层不变的东西.类型名加变量名;
float f;
double d;
long double g; //呵呵,变量名乱起的,没啥意思;
二、浮点常量
一个浮点常量的基本形式是:包含小数点的一个带符号的数字序列,接着是字母e或者E,然后就是代表10的指数的一个有符号值,后者必需是整数,否则错误,符号位可以省略,比如是+3的话直接写个3就行了,但是负数的话负号就不能省了哦,同时也可以省略指数部分(比如1.23),也可以省略小数点比如2e3;
下面写几个实例:
-1.56E+12
2.87e-3
3.14159
.2
.8E-5
100.
还有一点要注意的,就是中间不要用空格或一些制表符。
下面教大家如何区分float,double,long double;
比如有一个数1.0,编译器会把这个数当成是double类型,可是我们想保存为float怎么办,这时只要在1.0后面加一个f或F便可,默认编译器都把浮点常量当作double类型看待,long double方法一样,在long double常量后面加L或l便可。
在C99中为表示浮点数新增了一种十六进制格式的表示方法,这种格式使用0x或0X前辍,接着是十六进制数字,然后是p或者P,最后是2的指数,这二个要注意区分哦。下面我们来看一个数
0xa.1fp10
a是10.1f表示1/16加上15/256,p10表示2的10次方,整个数的十进制值为10364.0
2.4.7 复数和虚数类型
简单的讲,有三种复数类型,分别是float _Complex,double _Complex,long double _Complex。float _Complex变量包含两个float值,一个表示复数的实部,一个表示复数的虚部,与之类似,有3种虚数类型,分别是float _Imaginary,double _Imaginary,long double Imaginary.
如果你包含了complex.h头文件,就可以用complex代替_Complex,用imaginary代替_Imaginary.用符号I表示-1的平方根。
// 参考书籍:
// C++编码规范
// C Primer Plus 5th 好像这一次大哥写的很清楚哦!学习C的时候第一就是学习这些的!数据类型!
什么没有说float,double,long double;
的范围啊~
在讲int型的时候我已经写过一个程序怎么样查看一个类型占多少位,这里,大家也可以自己动手试着写一个程序,看看float、double、long double占多少位。
什么意思呢!不清楚~ #include <stdio.h>
int main(void)
{
printf ( "int: %d\n",sizeof(int));
printf ( "long int: %d",sizeof(long int));
printf ( "long: %d",sizeof(long));
printf ( "short int: %d",sizeof(short int));
printf ( "short: %d",sizeof(short));
printf ( "unsigned int: %d",sizeof(unsigned int));
printf ( "unsigned: %d",sizeof(unsigned));
printf ( "unsigned long: %d",sizeof(unsigned long));
printf ( "unsigned short: %d",sizeof(unsigned short));
printf ( "long long: %d",sizeof(long long));
return 0;
}
就是这个,可以把sizeof运算符里面的改成float类型
#include <stdio.h>
int main(void)
{
printf ( "float: %d\n",sizeof(float));
printf ( "double: %d",sizeof(double));
printf ( "long double: %d",sizeof(long double));
return 0;
}
呵呵,在不平同台的机上或者不同的编译器,这个是有区别的.....
所以我没有直接出来,也同时希望你们自己动一下手,这样有成就感,同时记得更加牢一些...
关于有效范围的话我现在教你们怎么算...
比如 int型占32位...
减去一位符号位就是31位(如果是无符号类的话就是32位,不用减)...
在计算机中数据是以二进制存在的,按权展开,我这里拿一个八位有符号的类型来讲解一下
减去一位符号位就是7位,按权展开.2的0次方2的一次方,2的二次方,2的三次方,一直到2的6次方然后依次相加,...结果为127.最大值为+127.最小值就为-(最大值+1);
所以一个八位的有符号类型的有范围是:-128~+127
呵呵,如果位数多的话这样累加下去的话会累死人的,比如上面的那个例子..直接2的7次方减一就行了.... 我想应该发一些数据结构了,例如链表,树了 希望官方能够多出一些数据结构与算法的文章
页:
[1]