各种数据类型介绍、变量与常量的介绍

2.1.1  ANSI C简介

C语言国际上广泛流行的一种计算机高级编程语言,它具有丰富的数据类型以及运算符,并为结构程序设计提供了各种数据结构和控制结构,同时具有某些低级语言的特点,可以实现大部分汇编语言功能,非常适合编写系统程序,也可用来编写应用程序。而且,C语言程序具有很好的可移植性。

1983年,美国国家标准协会(ANSI)根据C语言问世以来各种版本对C的发展和扩充制定了新的标准,并于1989年颁布,被称为ANSI CC89。目前流行的C编译系统都是以它为基础的。

2.1.2  GNU C简介

GNU项目始创于1984年,旨在开发一个类似UNIX,且为自由软件的完整的操作系统。GNU项目由很多独立的自由/开源软件项目组成,其官方站点为http://www.gnu.org。如今,这些GNU中的软件项目已经和Linux内核一起成为GNU/Linux的组成部分。

GCCGNU的一个项目,是一个用于编程开发的自由编译器。最初,GCC只是一个C语言编译器,它是GNU C Compiler 的英文缩写。随着众多自由开发者的加入和GCC自身的发展,如今的GCC已经是一个支持众多语言的编译器了,其中包括C,C++,Ada,Object CJava等。所以,GCC也由原来的GNU C Compiler变为GNU Compiler Collection,也就是 GNU编译器家族的意思

Linux下编程最常用的C编译器就是GCC,除了支持ANSI C外,还对C语言进行了很多扩展,这些扩展对优化、目标代码布局、更安全地检查等方面提供了很强的支持。本文把支持GNU扩展的C语言称为GNU C。本章主要介绍GNU C的基本语法,最后会简单介绍一些常用的扩展。GNU C可以理解为在标准C的基础上进行了扩展。在了解这些扩展之前,我们先简单回顾一下标准C语言。

C语言的数据类型根据其不同的特点,可以分为基本类型、构造类型和空类型,其中每种类型都还包含了其他一系列数据类型,它们之间的关系如图2-1所示。

 

2-1  常见数据类型分类

1.基本类型

基本类型是C语言程序设计中的最小数据单元,可以说是原子数据类型,而其他数据类型(如结构体、共用体等)都可以使用这些基本类型。

2.构造类型

构造类型正如其名字一样,是在基本数据类型的基础上构造而成的复合数据类型,它可以用于表示更为复杂的数据。

3.空类型

空类型是一种特殊的数据类型,它是所有数据类型的基础。要注意的是,空类型并非无类型,它本身也是一种数据结构,常用在数据类型的转换和参数的传递过程中。

 

C语言中,所有的数据都必须指定它的数据类型,它们大多有自己的类型标识符,如表2-1所示。

2-1                                                          数据类型及其标识符

   

   

整型

int

结构体

struct

字符型

char

共用体

union

浮点型

float(单精度)

空类型

void

double(双精度)

数组类型

枚举型

enum

指针类型

  基本数据类型

2.2.1  整型家族

变量是指在程序运行过程中其值可以发生变化的量。

1.整型变量

整型变量包括短整型(short int)、整型(int)和长整型(long int),它们都分为有符号(signed)和无符号(unsigned)两种,在内存中是以二进制的形式存放的。每种类型的整数占有一定大小的地址空间,因此它们所能表示的数值范围也有所限制。

要注意的是,不同的计算机体系结构中这些类型所占比特数有可能是不同的,表2-2列出的是常见的32位机中整型家族各数据类型所占的比特数。

2-2                                                  整型家族各类型所占的比特数

   

   

[signed] int

32

−21474836482147483647

unsigned int

32

04294967295

[signed] short [int]

16

−3276832767

unsigned short [int]

16

065535

long [int]

32

−21474836482147483647

unsigned long [int]

32

04294967295

 

上表中“[]”内的部分是可以省略的,如短整型可写作“short”。它们三者之间只是遵循如下的简单规则。

短整型≤整型≤长整型

若要查看适合当前计算机的各数据类型的取值范围,可查看文件“limits.h”(通常在编译器相关的目录下),如下是“limits.h”的部分示例。

#include <features.h>

#include <bits/wordsize.h>

/* 一个“char”的位数  */

#  define CHAR_BIT      8

 

/* 一个“signed char”的最大值和最小值 */

#  define SCHAR_MIN     (-128)

#  define SCHAR_MAX     127

 

/* 一个“signed short int”的最大值和最小值 */

#  define SHRT_MIN      (-32768)

#  define SHRT_MAX      32767

 

/* 一个signed int的最大值和最小值 */

#  define INT_MIN       (-INT_MAX - 1)

#  define INT_MAX       2147483647

 

/* 一个unsigned int的最大值和最小值 */

#  define UINT_MAX      4294967295U

 

/* 一个signed long int的最大值和最小值 */

/*若是64位机*/

#  if __WORDSIZE = = 64

#   define LONG_MAX     9223372036854775807L

#  else

#   define LONG_MAX     2147483647L

#  endif

#  define LONG_MIN      (-LONG_MAX - 1L)

 

/* 一个“unsigned long int”的最大值和最小值 */

/*若是64位机*/

#  if __WORDSIZE = = 64

#   define ULONG_MAX    18446744073709551615UL

#  else

#   define ULONG_MAX    4294967295UL

#  endif

 

在嵌入式开发中,经常需要考虑的一点就是可移植性的问题。通常,字符是否为有符号数会带来两难的境地,因此,最佳妥协方案就是把存储于int型变量的值限制在signed intunsigned int的交集中,这可以获得最大程度上的可移植性,同时又不牺牲效率。

 

2.整型常量

常量就是在程序运行过程中其值不能被改变的量。在C语言中,使用整型常量可以有八进制整数、十进制整数和十六进制整数3种,其中十进制整数的表示最为简单,不需要有任何前缀,在此就不再赘述。

八进制整数需要以“0”作为前缀开头,如下所示。

010    0762    0537    0107

十六进制的整数需要以“0x”作为前缀开头,由于在计算机中数据都是以二进制来进行存放的,数据类型的表示范围位数也一般都是4的倍数,因此,将二进制数据用十六进制表示是非常方便的,在Linux的内核代码中,到处都可见到采用十六进制表示的整数。

下面示例的几句代码就是从Linux内核源码中摘录出来的(/arch/arm/mach-s3c2410)。读者在这里不用知道这些代码的具体含义,而只需了解这些常量的表示方法。

unsigned long s3c_irqwake_eintallow = 0x0000fff0L;irq.c

if (pinstate = = 0x02) {……} pm.c

config &= 0xff; gpio.c

可以看到,第1句代码是使用常量“0x0000fff0L”对变量s3c_irqwake_eintallow进行赋初值,第2句是比较变量pinstate的值和0x02是否相等,而第3句则是对config进行特定的运算。

细心的读者可以看到,常量“0x0000fff0L”在最后有大写的“L”,这并不是十六进制的表示范围,那么这个“L”又是什么意思呢?

这就是整型常量的后缀表示。正如前文中所述,整型数据还可分为“长整型”、“短整型”、“无符号数”,整型常量可在结尾加上“L”或“l”代表长整型,“U”或“u”代表无符号整型。前面的第一句代码中由于指明了该常量0x0000fff0是长整型的,因此需要在其后加上“L”。

要注意变量s3c_irqwake_eintallow声明为“unsigned long”并不代表赋值的常量也一定是“unsigned long”数据类型。

2.2.2  实型家族

实型家族也就是通常所说的浮点数,在这里也分别就实型变量和实型常量进行讲解。

1.实型变量

实型变量又可分为单精度(float)、双精度(double)和长双精度(long double3种。表2-3列出的是常见的32位机中实型家族各数据类型所占的比特数。

2-3                                                    实型家族各类型所占比特数

   

   

float

32

67

−3.4×10−383.4×1038

double

64

1516

−1.7×10−3081.7×10308

long double

64

1819

−1.2×10−3081.2×10308

 

要注意的是,这里的有效数字是指包括整数部分的全部数字总数。它在内存中的存储方式是以指数的形式表示的,如图2-2所示。

由图2-2可以看出,小数部分所占的位(bit)越多,数的精度就越高;指数部分所占的位数越多,则能表示的数值范围就越大。下面程序就显示了实型变量的有效数字位数。

#include <stdio.h>

 

int main()

{

    float a;

    double b;

 

    a = 33333.33333;

    b = 33333.333333;

 

    printf("a=%f,b=%lf\n", a, b);

 

    return 0;

}

程序执行结果如下:

linux@ubuntu:~/book/ch2$ cc float.c  -Wall

linux@ubuntu:~/book/ch2$./a.out

a=33333.332031,b=33333.333333

可以看出,由于a为单精度类型,有效数字长度为7位,因此a的小数点后4位并不是原先的数据,而由于b为双精度类型,有效数字为16位。因此b的显示结果就是实际b的数值。

2.实型常量

浮点常量又称为实数,一般含有小数部分。

C语言中,实数只有十进制的实数,它又分为单精度实数和双精度实数,它们的表示方法基本相同。实数有两种表示方法,即一般形式和指数形式,所有浮点常量都被默认为double类型。表2-4概括了实型常量的表示方法。

2-4                                                          实型常量的表示方法

   

   

十进制表示

由数码09和小数点组成

0.00.255.7890.135.0300.

指数形式

<尾数>E(e) <整型指数>

3.0E5−6.8e18

 

从表2-4可以看出,一般形式的实数基本形式如下:

[+|-]M.N

例如:3.1-23.11123.1415926

指数形式的实数一般是由尾数部分、字母eE和指数部分组成。当一个实数的符号为正号时,可以省略不写,其表示的一般形式如下:

[+|-]M.N<e|E>[+|-]T

例如:

1.176e+10 表示1.176×1010

- 3.5789e-8 表示-3.5789×10-8

通常表示特别大或特别小的数。

举例:一个水分子的质量约为3.0×10-23g1夸脱水大约有950g,编写一个程序,要求输入水的夸脱数,然后显示这么多水中包含说少水分子。

示例程序如下:

#include <stdio.h>

 

int main(int argc,char **argv)

{

    float mass_mol = 3.0e-23;  

    float mass_qt = 950;       

    float quarts;

    float molecules;

   

    printf(“mass_mol=%f %e\n”, mass_mol, mass_mol);

    printf("Enter the number of quarts of water: ");

    scanf("%f", &quarts);

    molecules = quarts * mass_qt / mass_mol;

    printf("%f quarts of water contain %e(%f) molecules.\n",

            quarts, molecules);

 

    return 0;

}

程序执行结果如下:

linux@ubuntu:~/book/ch2$ cc water.c -o water –Wall

linux@ubuntu:~/book/ch2$./water

mass_mol=0.000000 3.000000e-23

Enter the number of quarts of water: 1

1.000000 quarts of water contain 3.166667e+25(31666665471894750551343104.000000) molecules.

可以看出,float不是一个确定的数值,比如写一个很小的数,用科学计数法可以表示出来,但以%f作输时显示为0。对于一些特别大的数据,使用实数的指数形式,更简洁,可读性更好。

2.2.3  字符型家族

1.字符变量

字符变量可以看作是整型变量的一种,它的标识符为“char”,一般占用一个字节(8bit),它也分为有符号和无符号两种,读者完全可以把它当成一个整型变量。当它用于存储字符常量时(稍后会进行讲解),实际上是将该字符的ASCII码值(无符号整数)存储到内存单元中。

实际上,一个整型变量也可以存储一个字符常量,而且也是将该字符的ASCII码值(无符号整数)存储到内存单元中。但由于取名上的不同,字符变量则更多地用于存储字符常量。以下一段小程序显示了字符变量与整型变量实质上是相同的。

#include <stdio.h>

int main()

{

      char a,b;

      int c,d;

      /*赋给字符变量和整型变量相同的整数常量*/

      a = c = 65;

      /*赋给字符变量和整型变量相同的字符常量*/

      b = d = 'a';

      /*以字符的形式打印字符变量和整型变量*/

      printf("char a = %c, int c = %c\n", a, c);

      /*以整数的形式打印字符变量和整型变量*/

      printf("char b = %d, int d = %d\n", b, d);

 

      return 0;

}

程序执行结果如下:

linux@ubuntu:~/book/ch2$ cc char.c -o char -Wall

linux@ubuntu:~/book/ch2$./char

char a = A, int c = A

char b = 97, int d = 97

由此可见,字符变量和整型变量在内存中存储的内容实质是一样的。

2-5显示了字符型数据占用的比特数。

2-5                                                          字符型所占的比特数

   

   

[signed] char

8

−128127

unsigned char

8

0255

 

示例程序如下:

#include <stdio.h>

 

int main()

{

    char ch1 = 129;

    unsigned ch2 = -1;

 

    printf("ch1=%c-%d,ch2=%c-%d\n",

            ch1, ch1, ch2, ch2);

 

    return 0;

}

程序执行结果如下:

linux@ubuntu:~/book/ch2$ cc char.c -o char -Wall

linux@ubuntu:~/book/ch2$./char

ch1=--127,ch2=--1

从程序结果可以看出,给字符型变量赋值越界时,编译程序没有语法错误,但是结果不准确。但是,当越界后如何处理,这和编译器有关,在这里,就不再进一步解释。

2.字符常量

字符常量是指用单引号括起来的一个字符,如’a’’D’’+’’?’等都是字符常量。以下是使用字符常量时容易出错的地方,请读者仔细阅读。

字符常量只能用单引号括起来,不能用双引号或其他括号。

字符常量只能是单个字符,不能是字符串。

字符可以是字符集中任意字符。但数字被定义为字符型之后就不能参与数值运算。如‘5’5是不同的。‘5’是字符常量,不能直接参与运算,而只能以其ASCII码值(053)来参与运算。

除此之外,C语言中还存在一种特殊的字符常量转义字符。转义字符以反斜线“\”开头,后跟一个或几个字符。转义字符具有特定的含义,不同于字符原有的意义,故称“转义”字符。

例如,在前面各例题printf函数的格式串中用到的“\n”就是一个转义字符,其意义是“回车换行”。转义字符主要用来表示那些用一般字符不便于表示的控制代码。表2-6就是常见的转义字符以及它们的含义。

2-6                                                           转义字符及其含义

   

ASCII代码

\n

回车换行

10

\t

水平跳到下一制表位置

9

\b

向前退一格

8

\r

回车,将当前位置移到本行开头

13

\f

换页,将当前位置移到下页开头

12

\\

反斜线符“\

92

\'

单引号符

39

\ddd

13位八进制数所代表的字符

 

\xhh

12位十六进制数所代表的字符

 

示例程序如下:

#include <stdio.h>

 

int main()

{

    char c1 = 'a', c2 = 'b', c3 = 'c';

    char c4 = '\101', c5 = '\116';

 

    printf("a%c b%c\tabc%c\n", c1, c2, c3);

    printf("\t\b%c %c\n", c4, c5);

 

    return 0;

}

程序执行结果如下:

linux@ubuntu:~/book/ch2$ cc char2.c -Wall

linux@ubuntu:~/book/ch2$./a.out

aa bb    abcc

       A N

2.2.4  枚举家族

在实际问题中,有些变量的取值被限定在一个有限的范围内。例如,一个星期内只有7天,一年只有12个月,一个班每周有6门课程等。如果把这些量说明为整型、字符型或其他类型显然是不妥当的。

为此,C语言提供了一种称为枚举的类型。在枚举类型的定义中列举出所有可能的取值,被定义为该枚举类型的变量取值不能超过定义的范围。

 

枚举类型是一种基本数据类型,而不是一种构造类型,因为它不能再分解为任何基本类型。

 

 

 

枚举类型定义的一般形式如下。

enum 枚举名

{

     枚举值表

};

在枚举值表中应罗列出所有可用值,这些值也称为枚举元素。

下例中是嵌入式Linux的存储管理相关代码“/mm/sheme.c”中的实例,“sheme.c”中实际实现了一个tmpfs文件系统。

/* Flag allocation requirements to shmem_getpage and shmem_swp_alloc */

enum sgp_type {

        SGP_QUICK,          /*不要尝试更多的页表*/

        SGP_READ,           /*不要超过i_size,不分配页表*/

        SGP_CACHE,          /*不要超过i_size,可能会分配页表*/

        SGP_WRITE,          /*可能会超过i_size,可能会分配页表*/

};

sgp_type具体含义的说明比较冗长,在此读者主要学习enum的语法结构。这里的sgp_type是一个标识符,它所有可能的取值有SGP_QUICKSGP_READSGP_CACHESGP_WRITE,也就是枚举元素。这些枚举元素的变量实际上是以整型的方式存储的,这些符号名的实际值都是整型值。

比如,这里的SGP_QUICK0SGP_READ1,依此类推。在适当的时候,用户也可以为这些符号名指定特定的整型值,如下所示。

/* Flag allocation requirements to shmem_getpage and shmem_swp_alloc */

enum sgp_type {

        SGP_QUICK = 2,      /*不要尝试更多的页表*/

        SGP_READ  = 9,  /*不要超过i_size,不分配页表*/

        SGP_CACHE = 19,     /*不要超过i_size,可能会分配页表*/

        SGP_WRITE = 64,     /*可能会超过i_size,可能会分配页表*/

};

2.2.5  指针家族

1.指针的概念

C语言之所以如此流行,其重要原因之一就在于指针,运用指针编程是C语言最主要的风格之一。利用指针变量可以表示各种数据结构,能很方便地使用数组和字符串,并能像汇编语言一样处理内存地址,从而编出精练而高效的程序。

指针极大地丰富了C语言的功能,是学习C语言中最重要的一环。能正确理解和使用指针是掌握C语言的一个标志。

在这里着重介绍指针的概念,指针的具体使用在后面的章节中会有详细的介绍。

何为指针呢?简单地说,指针就是地址。在计算机中,所有的数据都是存放在存储器中的。一般可以把存储器中的一个字节称为一个内存单元,不同的数据类型所占用的内存单元数不等,如整型量占4个内存单元(字节),字符量占1个内存单元(字节)等,这些在本章的2.2.1小节中已经进行了详细讲解。

为了正确地访问这些内存单元,必须为每个内存单元编号。根据一个内存单元的编号就可准确地找到该内存单元。内存单元的编号也叫做地址,通常也把这个地址称为指针。

 

内存单元的指针(地址)和内存单元的内容(具体存放的变量)是两个不同的概念。

 

2-3就表示了指针的含义。

从图2-3中可以看出,0x00100000等都是内存地址,也就是变量的指针,由于在32位机中地址长度都是32bit,因此,无论哪种变量类型的指针都占4个字节。

由于指针所指向的内存单元是用于存放数据的,而不同数据类型的变量占有不同的字节数,因此从图2-3中可以看出,一个整型变量占4个字节,故紧随其后的变量y的内存地址为变量x起始地址加上4个字节。

2.指针常量

事实上,在C语言中,指针常量只有唯一的一个NULL(空地址)。虽然指针是一个诸如0x00100011这样的字面值,但是因为编译器负责把变量存放在计算机内存中的某个位置,所以程序员在程序运行前无法知道变量的地址。当一个函数每次被调用时,它的自动变量(局部变量)每次分配的内存位置都不同,因此,把非零的指针常量赋值给一个指针变量是没有意义的。

3.字符串常量

字符串常量看似是字符家族中的一员,但事实上,字符串常量与字符常量有着较大的区别。字符串常量是指用一对双引号括起来的一串字符,双引号只起定界作用,双引号括起的字符串中不能是双引号(“”)和反斜杠(\),它们特有的表示法在转义字符中已经介绍。例如“China”、“Cprogram”、“YES&NO”、“33312-2341”、“A”等都是合格的字符串常量。

C语言中,字符串常量在内存中存储时系统自动在字符串的末尾加一个“串结束标志”,即ASCII码值为0的字符NULL,通常用“\0”表示。因此在程序中,长度为n个字符的字符串常量,在内存中占有n+1个字节的存储空间。

例如,字符串“China”有5个字符,存储在内存中时占用6个字节。系统自动在字符串最后加上NULL字符,其存储形式为图2-4所示。

要特别注意字符常量与字符串常量的区别,除了表示形式不同外,其存储方式也不相同。字符‘A’只占1个字节,而字符串常量“A”占2个字节。

本书之所以在指针家族处而不在字符家族中讲解字符串常量,是由于在程序中使用字符串常量会生成一个“指向字符串的常指针”。当一个字符串常量出现在一个表达式中时,表达式所引用的值是存储该字符串常量的内存首地址,而不是这些字符本身。

 

因此,用户可以把字符串常量赋值给一个字符类型的指针,用于指向该字符串在内存中的首地址。

  变量与常量

2.3.1  变量的定义

上一节中,读者学习了C语言中的基本数据类型。那么在程序中不同数据类型的变量如何使用呢?在C语言中使用变量采用先定义、后使用的规则,任何变量在使用前必须先进行定义

变量定义的基本形式如下。

说明符(一个或多个)变量或表达式列表

这里的说明符就是包含一些用于表明变量基本类型的关键字、存储类型和作用域。表2-7列举了一些常见基本数据类型变量的定义方式。

2-7                                                             变量的定义方式

   

   

整型

intunsignedshortlong

int a; unsigned long b;

浮点型

floatdouble

float a; double b;

字符型

charunsigned

char a; unsigned char b;

枚举类型

enum

enum a;

指针类型

数据类型 *

int *a, *b; char *c;

 

通常,变量在定义时也可以将其初始化,如:

int i = 5;

这条语句实际上转化为两条语句:

int i;           /*定义*/

i = 5;           /*初始化*/

此外,指针的定义形式在这里需着重说明。

指针的定义形式为标识符加上“*”。有些读者习惯把“*”写在靠近数据类型的一侧,如:

int* a;

虽然编译器支持这种定义形式,但会在阅读代码时带来困扰,例如:

int* b, c, d;

读者会很自然地认为上面这条语句把3个变量都定义为指向整型的指针。事实上,只有变量b是整型指针,而cd都是整型变量。因此,建议读者在定义指针变量时将“*”写在靠近变量名的一侧,如下所示。

int *b, *c, *d;

 

 

 

 

关于变量的定义和变量的声明是两个极易混淆的概念,在形式上也很接近。在对变量进行了定义后,存储器需要为其分配一定的存储空间,一个变量在其作用域范围内只能有一个定义。而变量的声明则不同,一个变量可以有多次声明,且存储器不会为其分配存储空间。在本书的稍后部分将会讲解它们使用上的区别。

2.3.2  typedef

typedefC语言的关键字,其作用是为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型(如intchar等)和自定义的数据类型(如struct等)。

其基本用法如下所示。

typedef 数据类型自定义数据类型

例如,用户可以使用以下语句。

typedef unsigned long uint32;

这样,就把标识符uint32声明为无符号长整型的类型了。之后,用户就可以用它来定义变量。

uint32 a;

此句等价于:

unsigned long a;

在大型程序开发中,typedef的应用非常广泛。目的有两点,一是给变量一个易记且意义明确的新名字,二是简化一些比较复杂的类型声明。

在嵌入式的开发中,由于涉及可移植性的问题,typedef的功能就更引人注目了。通过typedef可以为标识符取名为一个统一的名称,这样,在需要对这些标识符进行修改时,只需修改typedef的内容就可以了。

下面是“/include/asm-arm/type.h”里的内容。

#ifndef __ASSEMBLY__

/* 为有符号字符型取名为s8 */

typedef signed char s8;

/* 为无符号字符型取名为u8 */

typedef unsigned char u8;

/* 为有符号短整型取名为s16 */

typedef signed short s16;

/* 为无符号短整型取名为u16 */

typedef unsigned short u16;

/* 为有符号整型取名为s32 */

typedef signed int s32;

/* 为无符号整型取名为u32 */

typedef unsigned int u32;

/* 为有符号长长整型取名为s64 */

typedef signed long long s64;

/* 为无符号长长整型取名为u64 */

typedef unsigned long long u64;

2.3.3  常量的定义

1const定义常量

C语言中,可以使用const来定义一个常量。常量的定义与变量的定义很相似,只需在变量名前加上const即可,如下所示。

int const a;

以上语句定义了a为一个整数常量。那么,既然a的值不能被修改,如何让a拥有一个值呢?

这里,一般有两种方法,其一是在定义时对它进行初始化,如下所示。

const int a = 10;

其二,在函数中声明为const的形参在函数被调用时会得到实参的值。

在这里需要着重讲解的是const涉及指针变量的情况,先看两个const定义。

const int *a;

int * const a;

在第一条语句中,const用来修饰指针a所指向的对象,也就是说我们无法通过指针a来修改其指向的对象的值。但是a这个指针本身的值(地址)是可以改变的,即可以指向其他对象。

与此相反,在第二条语句中,const修饰的是指针a。因此,该指针本身(地址)的值是不可改变的,而该指针所指向的对象的值是可以改变的。

2define定义常量

define实际是一个预处理指令,其实际的用途远大于定义常量这一功能。在这里,首先讲解define定义常量的基本用法,对于其他用途在本书的后续章节中会有详细介绍。

使用define定义常量实际是进行符号替换,其定义方法为

#define 符号名替换列表

符号名必须符合标识符命名规则。替换列表可以是任意字符序列,如数字、字符、字符串、表达式等,例如:

#define MSG "I'm Antigloss!"       /*后面的所有MSG都会被替换为“I'm Antigloss!*/

#define SUM 99                    /*后面的所有SUM都会被替换为99*/

#define BEEP "\a"                 /*后面的所有BEEP都会被替换为“\a*/

习惯上,人们用大写字母来命名符号名,而用小写字母来命名变量。

 

预处理指令#define的最后面没有分号“;”,千万不要画蛇添足!

 

Linux内核中,也广泛使用define来定义常量,如用于常见的出错处理的头文件中,“include/asm-generic/errno-base.h”就有如下定义:

#define EPERM               1    /*操作权限不足*/

#define ENOENT             2    /*没有该文件或目录*/

#define ESRCH              3    /*没有该进程*/

#define EINTR              4    /*被系统调用所中止*/

#define EIO                5    /*I/O出错*/

#define ENXIO              6    /*没有这个设备或地址*/

#define E2BIG              7    /*命令列表太长*/

#define ENOEXEC            8    /*命令格式错误*/

转载于:https://www.cnblogs.com/wangjinshan/p/7056373.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值