C Hello World 实例

C 程序主要包括以下部分:

  • 预处理器指令
  • 函数
  • 变量
  • 语句 & 表达式
  • 注释

让我们看一段简单的代码,可以输出单词 “Hello World”:

  1. #include <stdio.h>
  2. int main()
  3. {
  4. /* 我的第一个 C 程序 */
  5. printf("Hello, World! \n");
  6. return 0;
  7. }

接下来我们讲解一下上面这段程序:

  1. 程序的第一行 #include 是预处理器指令,告诉 C 编译器在实际编译之前要包含 stdio.h 文件。
  2. 下一行 int main() 是主函数,程序从这里开始执行。
  3. 下一行 // 将会被编译器忽略,这里放置程序的注释内容。它们被称为程序的注释。
  4. 下一行 printf(…) 是 C 中另一个可用的函数,会在屏幕上显示消息 “Hello, World!”。
  5. 下一行 return 0; 终止 main() 函数,并返回值 0。

    编译 & 执行 C 程序

    接下来让我们看看如何把源代码保存在一个文件中,以及如何编译并运行它。下面是简单的步骤:

  6. 打开一个文本编辑器,添加上述代码。

  7. 保存文件为 hello.c
  8. 打开命令提示符,进入到保存文件所在的目录。
  9. 键入 gcc hello.c,输入回车,编译代码。
  10. 如果代码中没有错误,命令提示符会跳到下一行,并生成 a.out 可执行文件。
  11. 现在,键入 a.out 来执行程序。
  12. 您可以看到屏幕上显示 “Hello World”
    1. $ gcc hello.c $ ./a.out Hello, World!
    请确保您的路径中已包含 gcc 编译器,并确保在包含源文件 hello.c 的目录中运行它。
    如果是多个 c 代码的源码文件,编译方法如下:
    1. $ gcc test1.c test2.c -o main.out $ ./main.out

    C 基本语法

    我们已经看过 C 程序的基本结构,这将有助于我们理解 C 语言的其他基本的构建块。

    C 的令牌(Token)

    C 程序由各种令牌组成,令牌可以是关键字、标识符、常量、字符串值,或者是一个符号。例如,下面的 C 语句包括五个令牌:
    1. printf("Hello, World! \n");
    2. 这五个令牌分别是:
    3. printf ( "Hello, World! \n" ) ;

分号 ;

在 C 程序中,分号是语句结束符。也就是说,每个语句必须以分号结束。它表明一个逻辑实体的结束。
例如,下面是两个不同的语句:

  1. printf("Hello, World! \n"); return 0;

注释

C 语言有两种注释方式:
// 单行注释
// 开始的单行注释,这种注释可以单独占一行。
/ 单行注释 / / 多行注释 多行注释 多行注释 /
/ / 这种格式的注释可以单行或多行。
您不能在注释内嵌套注释,注释也不能出现在字符串或字符值中。

标识符

C 标识符是用来标识变量、函数,或任何其他用户自定义项目的名称。一个标识符以字母 A-Z 或 a-z 或下划线 开始,后跟零个或多个字母、下划线和数字(0-9)。
C 标识符内不允许出现标点字符,比如 @、$ 和 %。C 是区分大小写的编程语言。因此,在 C 中,_Manpower
manpower 是两个不同的标识符。下面列出几个有效的标识符:
mohd zara abc move_name a_123 myname50 _temp j a23b9 retVal

关键字

下表列出了 C 中的保留字。这些保留字不能作为常量名、变量名或其他标识符名称。

关键字 说明
auto 声明自动变量
break 跳出当前循环
case 开关语句分支
char 声明字符型变量或函数返回值类型
const 定义常量,如果一个变量被 const 修饰,那么它的值就不能再被改变
continue 结束当前循环,开始下一轮循环
default 开关语句中的”其它”分支
do 循环语句的循环体
double 声明双精度浮点型变量或函数返回值类型
else 条件语句否定分支(与 if 连用)
enum 声明枚举类型
extern 声明变量或函数是在其它文件或本文件的其他位置定义
float 声明浮点型变量或函数返回值类型
for 一种循环语句
goto 无条件跳转语句
if 条件语句
int 声明整型变量或函数
long 声明长整型变量或函数返回值类型
register 声明寄存器变量
return 子程序返回语句(可以带参数,也可不带参数)
short 声明短整型变量或函数
signed 声明有符号类型变量或函数
sizeof 计算数据类型或变量长度(即所占字节数)
static 声明静态变量
struct 声明结构体类型
switch 用于开关语句
typedef 用以给数据类型取别名
unsigned 声明无符号类型变量或函数
union 声明共用体类型
void 声明函数无返回值或无参数,声明无类型指针
volatile 说明变量在程序执行中可被隐含地改变
while 循环语句的循环条件

C99 新增关键字

_Bool _Complex _Imaginary inline restrict

C11 新增关键字

_Alignas _Alignof _Atomic _Generic _Noreturn
_Static_assert _Thread_local

C 中的空格

只包含空格的行,被称为空白行,可能带有注释,C 编译器会完全忽略它。
在 C 中,空格用于描述空白符、制表符、换行符和注释。空格分隔语句的各个部分,让编译器能识别语句中的某个元素(比如 int)在哪里结束,下一个元素在哪里开始。因此,在下面的语句中:

  1. int age;

在这里,int 和 age 之间必须至少有一个空格字符(通常是一个空白符),这样编译器才能够区分它们。另一方面,在下面的语句中:

  1. fruit = apples + oranges; // 获取水果的总数

fruit 和 =,或者 = 和 apples 之间的空格字符不是必需的,但是为了增强可读性,您可以根据需要适当增加一些空格。

C 数据类型

在 C 语言中,数据类型指的是用于声明不同类型的变量或函数的一个广泛的系统。变量的类型决定了变量存储占用的空间,以及如何解释存储的位模式。
C 中的类型可分为以下几种:

序号 类型与描述
1 基本类型:
它们是算术类型,包括两种类型:整数类型和浮点类型。
2 枚举类型:
它们也是算术类型,被用来定义在程序中只能赋予其一定的离散整数值的变量。
3 void 类型:
类型说明符 void 表明没有可用的值。
4 派生类型:
它们包括:指针类型、数组类型、结构类型、共用体类型和函数类型。

数组类型和结构类型统称为聚合类型。函数的类型指的是函数返回值的类型。在本章节接下来的部分我们将介绍基本类型,其他几种类型会在后边几个章节中进行讲解。

整数类型

下表列出了关于标准整数类型的存储大小和值范围的细节:

类型 存储大小 值范围
char 1 字节 -128 到 127 或 0 到 255
unsigned char 1 字节 0 到 255
signed char 1 字节 -128 到 127
int 2 或 4 字节 -32,768 到 32,767 或 -2,147,483,648 到 2,147,483,647
unsigned int 2 或 4 字节 0 到 65,535 或 0 到 4,294,967,295
short 2 字节 -32,768 到 32,767
unsigned short 2 字节 0 到 65,535
long 4 字节 -2,147,483,648 到 2,147,483,647
unsigned long 4 字节 0 到 4,294,967,295

注意,各种类型的存储大小与系统位数有关,但目前通用的以64位系统为主。
以下列出了32位系统与64位系统的存储大小的差别(windows 相同):
1-1 程序结构及变量类型 - 图1
为了得到某个类型或某个变量在特定平台上的准确大小,您可以使用 sizeof 运算符。表达式 sizeof(type) 得到对象或类型的存储字节大小。下面的实例演示了获取 int 类型的大小:

实例

  1. #include<stdio.h>
  2. #include<limits.h>
  3. int main(){
  4. printf("int 存储大小 : %lu \n", sizeof(int));
  5. return0;
  6. }

%lu 为 32 位无符号整数,详细说明查看 C 库函数 - printf()
当您在 Linux 上编译并执行上面的程序时,它会产生下列结果:
int 存储大小 : 4

浮点类型

下表列出了关于标准浮点类型的存储大小、值范围和精度的细节:

类型 存储大小 值范围 精度
float 4 字节 1.2E-38 到 3.4E+38 6 位有效位
double 8 字节 2.3E-308 到 1.7E+308 15 位有效位
long double 16 字节 3.4E-4932 到 1.1E+4932 19 位有效位

头文件 float.h 定义了宏,在程序中可以使用这些值和其他有关实数二进制表示的细节。下面的实例将输出浮点类型占用的存储空间以及它的范围值:

实例

  1. #include<stdio.h>
  2. #include<float.h>
  3. int main(){
  4. printf("float 存储最大字节数 : %lu \n", sizeof(float));
  5. printf("float 最小值: %E\n", FLT_MIN);
  6. printf("float 最大值: %E\n", FLT_MAX);
  7. printf("精度值: %d\n", FLT_DIG);
  8. return0;
  9. }

%E 为以指数形式输出单、双精度实数,详细说明查看 C 库函数 - printf()
当您在 Linux 上编译并执行上面的程序时,它会产生下列结果:

  1. float 存储最大字节数 : 4
  2. float 最小值: 1.175494E-38 float
  3. 最大值: 3.402823E+38 精度值: 6

void 类型

void 类型指定没有可用的值。它通常用于以下三种情况下:

序号 类型与描述
1 函数返回为空
C 中有各种函数都不返回值,或者您可以说它们返回空。不返回值的函数的返回类型为空。例如 void exit (int status);
2 函数参数为空
C 中有各种函数不接受任何参数。不带参数的函数可以接受一个 void。例如 int rand(void);
3 指针指向 void
类型为 void 的指针代表对象的地址,而不是类型。例如,内存分配函数 **void malloc( size_t size );** 返回指向 void 的指针,可以转换为任何数据类型。

如果现在您还是无法完全理解 void 类型,不用太担心,在后续的章节中我们将会详细讲解这些概念。

C 变量

变量其实只不过是程序可操作的存储区的名称。C 中每个变量都有特定的类型,类型决定了变量存储的大小和布局,该范围内的值都可以存储在内存中,运算符可应用于变量上。
变量的名称可以由字母、数字和下划线字符组成。它必须以字母或下划线开头。大写字母和小写字母是不同的,因为 C 是大小写敏感的。基于前一章讲解的基本类型,有以下几种基本的变量类型:

类型 描述
char 通常是一个字节(八位), 这是一个整数类型。
int 整型,4 个字节,取值范围 -2147483648 到 2147483647。
float 单精度浮点值。单精度是这样的格式,1位符号,8位指数,23位小数。
1-1 程序结构及变量类型 - 图2
double 双精度浮点值。双精度是1位符号,11位指数,52位小数。
1-1 程序结构及变量类型 - 图3
void 表示类型的缺失。

C 语言也允许定义各种其他类型的变量,比如枚举、指针、数组、结构、共用体等等,这将会在后续的章节中进行讲解,本章节我们先讲解基本变量类型。

C 中的变量定义

变量定义就是告诉编译器在何处创建变量的存储,以及如何创建变量的存储。变量定义指定一个数据类型,并包含了该类型的一个或多个变量的列表,如下所示:

  1. type variable_list;

在这里,type 必须是一个有效的 C 数据类型,可以是 char、w_char、int、float、double 或任何用户自定义的对象,variable_list 可以由一个或多个标识符名称组成,多个标识符之间用逗号分隔。下面列出几个有效的声明:

  1. int i, j, k;
  2. char c, ch;
  3. float f, salary;
  4. double d;

int i, j, k; 声明并定义了变量 i、j 和 k,这指示编译器创建类型为 int 的名为 i、j、k 的变量。
变量可以在声明的时候被初始化(指定一个初始值)。初始化器由一个等号,后跟一个常量表达式组成,如下所示:

  1. type variable_name = value;
  1. extern int d = 3, f = 5; // d 和 f 的声明与初始化
  2. int d = 3, f = 5; // 定义并初始化 d 和 f
  3. byte z = 22; // 定义并初始化 z
  4. char x = 'x'; // 变量 x 的值为 'x'

C 中的变量声明

变量声明向编译器保证变量以指定的类型和名称存在,这样编译器在不需要知道变量完整细节的情况下也能继续进一步的编译。变量声明只在编译时有它的意义,在程序连接时编译器需要实际的变量声明。
变量的声明有两种情况:

  • 1、一种是需要建立存储空间的。例如:int a 在声明的时候就已经建立了存储空间。
  • 2、另一种是不需要建立存储空间的,通过使用extern关键字声明变量名而不定义它。 例如:extern int a 其中变量 a 可以在别的文件中定义的。
  • 除非有extern关键字,否则都是变量的定义。
    1. extern int i; //声明,不是定义
    2. int i; //声明,也是定义

    实例

    尝试下面的实例,其中,变量在头部就已经被声明,但是定义与初始化在主函数内: ```c

    include

// 函数外定义变量 x 和 y int x; int y; int addtwonum() { // 函数内声明变量 x 和 y 为外部变量 extern int x; extern int y; // 给外部变量(全局变量)x 和 y 赋值 x = 1; y = 2; return x+y; }

int main() { int result; // 调用函数 addtwonum result = addtwonum();

  1. printf("result 为: %d",result);
  2. return 0;

}

  1. 当上面的代码被编译和执行时,它会产生下列结果:<br />result 为: 3
  2. <a name="HWpgc"></a>
  3. ## C 中的左值(Lvalues)和右值(Rvalues)
  4. C 中有两种类型的表达式:
  5. 1. **左值(lvalue):**指向内存位置的表达式被称为左值(lvalue)表达式。左值可以出现在赋值号的左边或右边。
  6. 1. **右值(rvalue):**术语右值(rvalue)指的是存储在内存中某些地址的数值。右值是不能对其进行赋值的表达式,也就是说,右值可以出现在赋值号的右边,但不能出现在赋值号的左边。
  7. 变量是左值,因此可以出现在赋值号的左边。数值型的字面值是右值,因此不能被赋值,不能出现在赋值号的左边。下面是一个有效的语句:
  8. ```c
  9. int g = 20;

但是下面这个就不是一个有效的语句,会生成编译时错误:

  1. 10 = 20;