C Primer Plus. Fifth Edition 翻译Chapter 3 数据和C (Data and C)第二部分
3.4 基本C数据类型
在这里,我们将对每种类型,描述如何声明一个变量,如何表示一个常量,以及典型的应用。一些老的C编译器或许不会支持所有的这些数据类型,所以你不要检查下相关的文档看是否能有效使用这些数据类型。
Int类型
C提供了许多整型类型,或许你会有疑问,会什么要提供这么多,一种不就足够了吗?答案就是C给程序员提供了匹配一种类型到特定使用的可选性。特别,C整型对于提供的值的变化,以及负数是否将被使用。Int是基本的选择,但是如果你想能得到符合特定任务或机器的不同选择,同样也是可以的。
Int整型是一个符号整型。也就是说,可以为0,也可以为负数或者正数。值得范围取决于计算机系统。典型意义上,一个int使用一个机器字进行存贮。如果早期的IBM PC,则就是16位字,所以一个int的范围就是-32768到32767。其他的可以见表3.3。一般,系统会使用一个特定的位来表示符号位,第15章将会讨论通常的方法。
声明一个int变量
正如你在第2章中所见,关键字int将被用于声明一个基本的整型变量。先是int,然后是一个被选择的变量名字,最后是一个分号。如果为了声明更多的变量,你既可以分开分别声明,或者在int之后,你可以在每个变量名后使用逗号,最后一个使用分号。下面给出例子。
int erns;
int hogs, cows, goats;
这些声明创建了变量,但是没有给他们提供值。我们已经看到过有两种方法能让他们在程序中得到值。首先,是赋值:cows = 112;
第二种,则是通过使用一个函数,比如可以使用scanf()。下面我们将看到第三种方法。
初始化一个变量
也就是说,给变量一个开始的或者说初始化的值。在C中,可以作为声明的一部分,跟随在变量名后面,使用操作符(=)以及你所希望给予的值。下面是例子:
int hogs = 21;
int cows = 32, goats = 14;
int dogs, cats = 94; /* valid, but poor, form 。在这里,只有cats被赋予初值*/
简要地说,这些声明为变量创建和label了一个存贮空间,以及赋予了一个初值。见图3.4。
图3.4 定义和初始化一个变量
定义int常量
当你在C中写了一个没有带小数点和指数部分的数字,C会把它作为一个整型量。C把大部分整型常量看作是int类型。但是非常大的整型量则要不同对待,在后面可以在"long Constants and long long Constants Constants and long long Constants."部分看到对于long int类型的讨论。
打印int值
你可以使用printf()函数,使用%d来标明在一行中整型量在哪里被打印。下面给出一个样本程序,listing3.2 print1.c
/* print1.c-displays some properties of printf() */
#include <stdio.h>
int main(void)
{
int ten = 10;
int two = 2;
printf("Doing it right: ");
printf("%d minus %d is %d/n", ten, 2, ten - two );
printf("Doing it wrong: ");
printf("%d minus %d is %d/n", ten ); // forgot 2 arguments
return 0;
}
编译并运行得到输出:
Doing it right: 10 minus 2 is 8
Doing it wrong: 10 minus 10 is 2
第一句是正确的,第二句第一个%d是正确的赋予了10,但是后面两个%d则会根据内存中的值,随机被赋予值,上面我们看到一个被赋予了10,另一个则是2。一般C会根据函数所需要的参数进行判断,但是由于printf()函数可以有1个,2个。。。不同的参数,所以C编译不会给出错误,因此在使用printf()函数的时候要注意。
8octal进制和16hexadecimal进制
在C中,需要使用一个前缀符来表示,0x或者0X(zero-ex)表示你使用的是16进制。0(zero)表示你使用的是8进制。所以16可以被表示为16进制的0x10或0X10,也可以表示为8进制的020
显示8进制和16进制
使用%o显示8进制,使用%x显示16进制。如果你想显示前缀0, 0x, 和0X,你可以使用%#o, %#x, 和%#X。可以看一个样本程序listing3.3
//Listing 3.3. The bases.c Program
/* bases.c--prints 100 in decimal, octal, and hex */
#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;
}
编译运行显示:
dec = 100; octal = 144; hex = 64
dec = 100; octal = 0144; hex = 0x64
其他整型类型
C提供了3种关键字来改变基本整型类型:short, long, 和 unsigned.下面给出需要记住的几点:
・ 类型short int或,简写的short,可能比int存贮的空间小,因此当仅仅需要小数字的使用时,使用short会节省空间。就像int一样,short也是一个符号型类型。
・ 类型long int,或long可能比int使用更多的存贮空间,因此也能让你表达更大的整型值,类似于int,long也是一个符号型。
・ 类型long long int,或long long(在C99标准中介绍),可能比long使用的空间还要大,因此让你能表达更大的整型值,符号型。
・ 类型unsigned int,或unsigned被用于表示一个非负整数的变量。因此不使用符号位,所以表大的范围移了一位,比如16位允许的范围是0到65535,而不是-32768到32767。
・ 类型unsigned long int, or unsigned long, and unsigned short int, or unsigned short在C90标准中被认为有效。而C99增加了unsigned long long int, or unsigned long long。
・ 关键词signed被用于符号整型的时候是被默认的。比如short, short int, signed short, and signed short int 是相同的类型。
宣布不同的整型类型,下面是一些例子
long int estine;
long johns;
short int erns;
short ribs;
unsigned int s_count;
unsigned players;
unsigned long headcount;
unsigned short yesvotes;
long long ago; //C99标准承认
*整型溢漏overflow
如果一个整型得到了一个比他类型更大的值时,会发生什么呢?下面看一个程序:
/* toobig.c-exceeds maximum int size on our system */
#include <stdio.h>
int main(void)
{
int i = 2147483647;
unsigned int j = 4294967295;
printf("%d %d %d/n", i, i+1, i+2);
printf("%u %u %u/n", j, j+1, j+2);
return 0;
}
对我们系统的结果:(译者:由于不同的系统,int所表示的范围也不同,所以有时你或许取一个更大的值)
2147483647 -2147483648 -2147483647
4294967295 0 1
可以从程序中看出,当发生溢出时,数值会变为开始的数值。对于j,是一个无符号型,所以当溢出时,变为了0,而对于i,由于是一个符号型,所以溢出时变为了-2147483648。
Long常量和long long常量
通常,当你使用一个数字比如2345的时候,系统会把它作为一个int类型,但是当你使用一个数字比如10000000000时,由于int不能容忍这么大的数,所以C会把它作为一个long 或者 long long.
有时候你或许需要让编译器把一个小的数字作为一个long整型量对待,这时候你就可以使用后缀l(L).比如7L,020L,0x10L。类似的,longlong 的时候,使用后缀ll或(LL),u(U)则表示为无符号型。比如5ull,10LLU.
打印short, long, long long, and unsigned类型
Unsigned int:%u ;long:%ld ; long o:%l0
C也可以使用前缀h来表示short类型。因此%hd显示一个十进制的short整型。%ho为八进制形式。举列说明
//Listing 3.4. The print2.c Program
/* print2.c-more printf() properties */
#include <stdio.h>
int main(void)
{
unsigned int un = 3000000000; /* system with 32-bit int */
short end = 200; /* and 16-bit short */
long big = 65537;
long long verybig = 12345678908642;
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, big); //%hd short int
printf("verybig= %lld and not %ld/n", verybig, verybig);
return 0;
}
un = 3000000000 and not -1294967296
end = 200 and 200
big = 65537 and not 1
verybig= 12345678908642 and not 1942899938
从上面这个例子可以看出,使用错误的结构就会产生自己所不期望的结果。所以你必须有责任使两者匹配。
对于计算机,short和int是两种不同的大小,但是如果都作为int传递值将会更快一点。
*Match the Type printf() Specifiers