张银峰的编程课堂

数值类型与字面量

C语言提供的数值类型有:

  • 整型:
    • char:字符型,占用一个字节,可以存放本地字符集中的一个字符,本质是一种小整型。
    • int:整型,通常反映了所用机器中整数的最自然长度。
  • 浮点型:
    • float:单精度浮点型
    • double:双精度浮点型

从符号特性角度看,整型可划分为有符号(signed)与无符号数(unsigned)两种类型。有符号类型可以表达负数的概念,无符号类型表达0与正整数的概念。需要注意的是,C语言自身并没有规定char类型的符号特性,这通常由编译器指定,大多数时候都是有符号的。

         char c1
signed   char c2;   // 可表达负数,因为char的本质是8位的整型。
unsigned char c3;

         int b1;    // 省略signed,等价于b2的定义
signed   int b2;    // 显示的加上signed,等价于b1的定义
unsigned int b3;

从空间占用大小视角看,整型有长(long)短(short)之分,这使得我们可以根据需要选择最优的解。

  • 整型(int)至少应该和短整型(short int)一样长
  • 长整型(long int)至少应该和整型(int)一样长
  • 字符类型(char)始终是8bit,没有长短之分

现代编译器环境下:

  • short类型通常是16位
  • long类型通常是32位
  • int类型具体取决于编译器实现,通常也是32位。
short int a1;
short     a2;   // 与a1等价
long  int b1;
long      b2;   // 与b1等价

根据上面的示例,可以看出在定义int型变量时:

  • 从符号角度而言,关键字signed可以省略,unsigned则不行。
  • 从长短特性而言,关键字int可以省略。

对于浮点类型,它始终表达的是有符号数概念;同时可以使用long修饰,即可以定义 long double 型的变量。

字面量

字面量(literal)是字面值常量的缩写,常用于变量初始化。

  • long类型的字面量可以以字母l或L结尾,如987654L;无符号字面量以字母u或U结尾,如256U;后缀ul或UL表示字面量类型是unsigned long,如256UL;没有后缀的字面量为int类型。
  • 没有后缀的浮点字面量为double类型。后缀f或F表示float类型,如3.14f;后缀l或L则表示long double类型。
9;      // int
9U;     // unsigned int
9UL;    // unsigned long int
3.14;   // double
3.14f;  // float
3.14L;  // long double

这里我们使用sizeof运算符测试一下这些类型的大小。

#include <stdio.h>

int main()
{
    printf("sizeof(3.14):  %d bytes\n", sizeof(3.14));     // double
    printf("sizeof(3.14f): %d bytes\n", sizeof(3.14f));    // float
    printf("sizeof(3.14L): %d bytes\n", sizeof(3.14L));    // long double

    printf("sizeof(9):     %d bytes\n", sizeof(9));        // int
    printf("sizeof(9U):    %d bytes\n", sizeof(9U));       // unsigned int
    printf("sizeof(9UL):   %d bytes\n", sizeof(9UL));      // unsigned long int

    return 0;
}

glimix.com

整型除了以十进制表示外,还可以用八进制或十六进制表示。后缀L/U同样可应用于它们;如,0x43UL。

  • 前缀0的整型字面量表示它为八进制形式,如十进制数67可以也写八进制形式0103。
  • 前缀0x或0X的整型字面量表示表示它为十六进制形式,如十进制数67可以也写八进制形式0x43或0X43。

我们也可以用转义字符的形式表达八进制或十六进制一字节单位的数值。

  • '\ooo':ooo代表1-3个八进制数字(0...7)
  • '\xhh':hh是一个或多个十六进制数字(0...9, a...f, A...F)

比如对回车(CR)/换行(LR)符,以10/8/16进制的形式可以表达如下:

// 十进制形式
#define CR  13
#define LF  10

// 八进制转义字符形式定义
#define CR  '\015'
#define LF  '\010'

// 十六进制转义字符形式定义
#define CR  '\xD'
#define LF  '\xA'

示例程序以隐晦的方式打印了数值64与127。

#include <stdio.h>

int main()
{
    char newline = '\12'; // 换行符'\n'的八进制转义表示
    printf("'\\100' = %d%c'\\x7F' = %d\n", '\100', newline, '\x7F');
    return 0;
}

glimix.com

需要说明的是,一个字符字面量是一个整型,如'x'、'0'、'BM'。字符在字符集中的数值就是字符常量的值。例如,在ASCII字符集中,'0'的值为48,也就是说字面量'0'的值就是48;而字面量'BM'的值就是0x424D,即十进制值16973。

#include <stdio.h>

int main()
{
    printf("sizeof('A'):  %d bytes\n", sizeof('A'));
    printf("sizeof('AB'): %d bytes\n", sizeof('AB'));

    printf("\n");

    printf("'B' = 0x%x\n", 'B');
    printf("'M' = 0x%x\n", 'M');
    printf("'BM' = %d\n", 'BM');

    return 0;
}

glimix.com

格式控制符

由于符号与长短修饰的引入,格式化控制符也有相应的变化,下表格总结了C语言常用的格式控制符,说明一列表示它们应用输入或输出的含义。

格式控制符 数据类型 说明
d/i int 有符号整型值的十进制。
o unsigned int 无符号8进制整型。
u unsigned int 无符号10进制整型。
x/X unsigned int 无符号16进制整型,不输出前缀0x。
f double 单精度、双精度浮点数。
e/E double 以e表达的,科学计数法表示的浮点数,基数为10。
a/A double 以p表达的,科学计数法表示的16进制浮点数,基数为2。
g/G double 有效位数,如:%.8g表示保留8位有效数字。
c char 字符型。

示例程序演示了各种格式控制符的使用。

#include <stdio.h>

int main()
{
    printf("%o\n", 256U);
    printf("%u\n", 0xFFU);
    printf("%x\n", 1024);
    printf("%X\n", 1024);

    printf("\n");
    printf("%f\n", 3.1415926535898f);
    printf("%f\n", 3.1415926535898);
    printf("%e\n", 3.1415926535898);
    printf("%a\n", 3.1415926535898);

    printf("\n");
    printf("%.g\n",  3.1415926535898);
    printf("%.6g\n", 3.1415926535898);
    printf("%.7g\n", 3.1415926535898);
    printf("%.8g\n", 3.1415926535898);

    return 0;
}

glimix.com