数据与C

变量与常量

为了能够更加方便的使用数据,程序员会将在程序运行期间会改变或赋值的数据使用变量进行保存。常量则是预先定义好,在程序运行期间不会改变的固定值

变量和常量就好像是一个盒子,可以用来装东西(数据)。在计算机中,数据是存放在内存中的,存放数据的内存空间程序员为了方便以后的使用,都会起一个好记的名字。这个名称也由字母、数字和下划线组成,必须要以字母和下划线开头。由于C语言是对大小写敏感的,所以大写字母和小写字母是不同的,也就是变量名abc和Abc是两个不同的变量。

数据类型

不同的数据类型有不同的含义,有的数据类型表示整数,有的表示字符,有的表示浮点数。常量可以是任何的数据类型,通过常量的值识别(100是整数,123.45是浮点数)。而变量则需要指定数据类型。在C语言中有很多种数据类型,从最初的K&R给出的7个数据类型关键字,再到C90添加的2个新的关键字,到最后的C99添加的3个关键字

最初K&R给出的关键字 C90标准添加的关键字 C99标准添加的关键字
int signed _Bool
long void _Complex
short _Imaginary
unsigned
char
float
double

int、long、short、unsigned和C90新添加的signed关键字用于表示整数类型,unsigned表示无符号数,signed则表示有符号数,整数类型的例子:unsigned short int 和 long long int

char关键字用于存放字母和其他字符(如:$、%等),char也可以用来表示较小的整数

float、double和long double表示浮点数

_Bool表示布尔类型(true或false)

_Complex和_Imaginary分别表示复数和虚数

存储大小

不同的数据类型可以存放的数据大小是不同的,能够存放的数据越多,值越大。

数据类型 存储大小
char 1字节
int 2或4字节()
short 2字节
long 4字节
float 4字节
double 8字节
long double 16字节

在C语言中,可以通过sizeof运算符查看数据类型存储字节的大小

#include

int main()
{
    printf("char 的存储大小: %d\n", sizeof(char));
    printf("short 的存储大小: %d\n", sizeof(short));
    printf("int 的存储大小: %d\n", sizeof(int));
    printf("long 的存储大小: %d\n", sizeof(long));
    printf("float 的存储大小: %d\n", sizeof(float));
    printf("double 的存储大小: %d\n", sizeof(double));
    printf("long double 的存储大小: %d\n", sizeof(long double));

    return 0;
}

运行结果:

数据与C_第1张图片

这里使用到的printf()函数,后面会进行讲解,目前只需要知道printf()是用来打印内容到屏幕上的就可以了。

变量的定义

C语言提供了很多种数据类型,在定义变量时需要指定变量的数据类型,如整数可以使用int类型,小数可以使用float类型等,下面将开始介绍如何定义变量。

定义变量

定义变量的语法:数据类型 变量名;

举个例子,下面的程序用于计算两个整数的和

#include

int main()
{
    int num1;   //定义一个变量num1,用于存放第一个数
    int num2;   //定义一个变量num2,用于存放第二个数
    int sum;    //定义一个变量sum,用于存放两个数的和
    
    num1 = 100;        //将整数100赋值给变量num1
    num2 = 200;
    sum = num1 + num2;  //计算num1与num2相加,并将值赋值给sum变量

    printf("num1 + num2 = %d\n", sum);      // 将sum的值打印到屏幕

    return 0;
}

运行结果:

在声明num1和num2变量时,并没有给它们提供初始值。num1和num2是通过后面的 num1 = 100;num2 = 200; 获取到值的,这种行为称为初始化。初始化就是给变量一个初始值。

定义变量时初始化

在上面的例子中,定义变量与给初始化变量是分成两步的,也可以将这两步合并在一起,将程序修改后如下:

#include

int main()
{
    int num1 = 100;   //定义变量num1并将100赋值给num1
    int num2 = 200;
    int sum = num1 + num2;   //num1与num2相加后的结果赋值给sum变量

    printf("num1 + num2 = %d\n", sum);      // 将sum的值打印到屏幕

    return 0;
}

连续定义多个变量

修改后的程序比之前的简洁了,接着我们发现num1和num2的数据类型是相同的,都是int类型,那么这两个变量就可以一起定义,还是上面的例子,修改后如下:

#include

int main()
{
    int num1 = 100, num2 = 200;     //同时声明num1和num2并赋值
    int sum = num1 + num2;   //num1与num2相加后的结果赋值给sum变量

    printf("num1 + num2 = %d\n", sum);      // 将sum的值打印到屏幕

    return 0;
}

需要注意的是,为了不让人误会在同时定义多个变量时,有的变量不需要初始化,而有的变量需要进行初始化。那么不建议写在一起,建议分开定义,如int num1, num2= 200; 这样写很容易让人误以为num1和num2的值都是200,所以不建议这么写,当然这么写是不会报错的。

常量的定义

通过一个例子开始讲解常量的使用,下面的程序的作用是计算圆的周长和面积:

#include

int main(void)
{
    float pi = 3.14159;     //圆周率
    int r = 5;              //圆的半径

    float area = pi * r * r;        //计算圆的面积
    float circum = 2 * pi * r;      //计算圆的周长

    printf("半径为 %d 的圆面积是: %.2f, 周长是: %.2f", r, area, circum);

    return 0;
}

通过上面的例子可以知道变量也可以当做常量来使用,但是在实际使用的时候不建议这么使用,因为在程序运行过程中有可能会将定义的变量改变,变量并非不可改变的。那有没有更好的定义常量的方法呢?有,这就需要使用预处理语句定义一个常量,这样定义的常量也被称为符号常量。语法是:#define NAME value

使用预处理语句,修改上面的例子:

#include
#define PI 3.14159     //使用预处理语句定义圆周率


int main(void)
{
    int r = 5;              //圆的半径

    float area = PI * r * r;        //计算圆的面积
    float circum = 2 * PI * r;      //计算圆的周长

    printf("半径为 %d 的圆面积是: %.2f, 周长是: %.2f", r, area, circum);

    return 0;
}

预处理语句的作用是在编译的时候将PI替换为3.14159,这样就达到了常量的作用了。预处理语句一定要写在顶部,并且PI和3.14159之间是没有等号和结束时也没有分号的。前面也说了预处理语句是在编译时替换掉值,如果有了等号和分号,那么等号和分号也会变成要替换的值了。

还有一种方法是使用限定符 const 将变量限定为只读,修改上面的例子如下:

#include

int main(void)
{
    const float pi = 3.14159;     //使用限定符const,定义常量圆周率
    int r = 5;                    //圆的半径

    float area = pi * r * r;        //计算圆的面积
    float circum = 2 * pi * r;      //计算圆的周长

    printf("半径为 %d 的圆面积是: %.2f, 周长是: %.2f", r, area, circum);

    return 0;
}

使用 const 限定符定义的变量pi可以使用,可以使用 printf() 打印值,但就是无法修改值。另外需要注意的是使用 const 限定符定义的是变量,不是常量。

输入输出

输出

在C语言中,通过printf()将内容输出到屏幕上,printf()也被称为格式化输出,可以让变量以某种格式输出到屏幕上,如 %d为以整数的形式显示,%f以浮点数的形式显示,下表列出了一些转换说明和各自对应的输出类型:

转换说明 输出
%a 浮点数、十六进制和p记数法
%A 浮点数、十六进制和p记数法
%c 单个字符
%d 有符号十进制整数
%e 浮点数,e记数法
%E 浮点数,e记数法
%f 浮点数,十进制记数法
%g 根据值的不同,自动选择%f或%e。%e格式用于指数小于-4或者大于或等于精度时
%G 根据值的不同,自动选择%f或%E。%E格式用于指数小于-4或者大于或等于精度时
%i 有符号十进制整数(与%d相同)
%o 无符号八进制整数
%p 指针
%s 字符串
%u 无符号十进制整数
%x 无符号十六进制整数,使用十六进制数0f
%X 无符号十六进制整数,使用十六进制数0F
%% 打印一个百分号

一开始不需要全部都记住,只需要记住几个常用的(如:%d,%f,%c)即可,其他的用到在看就可以了,用的多了就记住了。下面的例子是将一个整数以八进制和十六进制的形式显示:

#include

int main(void)
{
    int num = 100; 

    printf("100 的八进制为 %o\n", num);        //显示num的八进制
    printf("100 的八进制为 %#o\n", num);        //显示num的八进制时,并在前面加上前缀
    printf("100 的十六进制为 %x\n", num);        //显示num的十六进制
    printf("100 的十六进制为 %#x\n", num);    //显示num的十六进制,并在前面加上前缀
    return 0;
}

运行结果:

可以通过printf()函数配合%o和%x打印出数值的八进制形式和十六进制形式。#只是为了显示前缀,八进制以0开头,十六进制以0x开头

有的读者可能不太了解什么是八进制和十六进制,那就简单的介绍一下。我们日常说的10,100,123等数字,都是十进制,可以发现这些数字都是逢十进一,而八进制和十六进制同理,八进制就是逢八进一,十六进制是逢十六进一。有的读者就会问了,逢十六进一?那要怎么表示十以上的数呀?十六进制由1到9和a到f(也可以是A到F)组成,没错,a到f分别表示10到15。

参数与陷阱

在使用printf()scanf() 时需要确保转换说明的数量、类型与后面的参数数量、类型匹配。由于 printf()scanf() 的参数是可变的,所以无法检查出参数的个数和类型是否正确。

那如果参数个数不匹配会怎样呢?

#include

int main(void)
{
    int num1 = 1;
    float num2 = 1.23;

    printf("%d %d %d\n", num1, num1, num1, num1);   //参数太多
    printf("%d %d %d\n", num1);   //参数太少
    printf("%d\n", num2);           //类型不匹配


    return 0;
}

运行结果:

当使用%d打印一个浮点数时,不会将这个浮点数转换为int类型。在不同的平台下,缺少参数或参数类型不匹配导致的结果会不相同。

输入

在前面的两个数相加的例子中,两个相加的数是预先就设置好的,当要计算其他整数相加时,需要修改源文件并生成新的可执行文件,这就很麻烦,这是就可以让用户输入要进行计算的两个整数。

要想获取用户的输入可以使用scanf()进行接收,使用的方法与printf()相似,%d表示要接收整数,%f表示要接收一个浮点数。

修改程序:

#include

int main(void)
{
    int num1, num2;     //同时声明num1和num2
    scanf("%d %d", &num1, &num2);       //获取用户输入的num1和num2的值
    int sum = num1 + num2;   //num1与num2相加后的结果赋值给sum变量

    printf("num1 + num2 = %d\n", sum);      // 将sum的值打印到屏幕

    return 0;
}

运行结果:

运行完程序,应该可以发现如果这是给程序员自己使用,那当然没有任何问题,但是给其他人使用,会出现不知道要干嘛的情况。所以应该在程序接收用户输入之前,告诉用户要做什么,再次修改程序:

#include

int main(void)
{
    int num1, num2;     //同时声明num1和num2
    printf("请输入两个需要相加的整数(例:12 34):");    //提示用户输入两个整数
    scanf("%d %d", &num1, &num2);       //获取用户输入的num1和num2的值
    int sum = num1 + num2;               //num1与num2相加后的结果赋值给sum变量

    printf("num1 + num2 = %d\n", sum);  // 将sum的值打印到屏幕

    return 0;
}

运行结果:

细心的读者会发现在num1和num2的前面有一个&符号,那这个&符号表示的是什么意思呢?&符号表示获取地址,整个语句就是将获取到的整数放入到num1和num2的地址中。

当读取的是基本的数据类型的值时需要使用&符号,而读取的是字符串时,不要使用&符号。

整数溢出

当一个整数类型超出了它能表示的最大值会出现溢出,通过一个例子观察溢出后的结果

#include

int main(void)
{
    int i = 2147483647;     //定义一个有符号整数类型的变量i并初始化为最大值
    unsigned int j = 4294967295;       //定义一个无符号整数类型的变量j并初始化为最大值

    printf("%d %d %d\n", i, i+1, i+2);
    printf("%u %u %u\n", j, j+1, j+2);
    return 0;
}

运行结果:

通过观察可以发现当一个数超过自身能够表示的最大值时,会从最小值开始。当发生溢出时系统没有告诉用户,所以在编程时需要注意。

char类型

char类型用于存放字符(如:字母或标点符号),但char其实是整数类型,因为char实际上保存的是整数,而不是字符。有的读者就会有疑问了,存储整数,那要怎么知道是哪个字符呢?在计算机中使用数字编码处理字符,即使用整数表示字符,在ASCII编码中65表示大写字母"A",标准的ASCII的范围是0~127,完全可以使用char类型进行存储

声明char类型变量

char类型的变量在赋值时,值需要使用单引号括起来,如:char ch = 'A'; ,而不能是 char ch = A; 。如果没有被单引号括起来,此时A表示一个变量名,而不是字符A。

char类型也可以直接保存整数,如 char ch = 65; ,但是不建议这样使用,这样使用需要系统支持ASCII码,最好还是使用 ‘A’ 替换 65。

举个例子

用户输入一个字符,将这个字符对应的ASCII码打印在屏幕上:

#include

int main(void)
{
    char ch;    //定义变量ch,用于接收用户输入

    printf("请输入一个字符(如:A):");
    scanf("%c", &ch);       //接收用户输入的字符
    printf("%c 对应的整数为 %d\n", ch, ch);
    return 0;
}

运行结果:

转义字符

使用特殊的符号序列表示一些特殊的字符,这些符号序列就叫做转义序列,下表列出了转义序列及其含义

转义序列 含义
\a 警报(ANSI C)
\b 退格
\f 换页
\n 换行
\r 回车
\t 水平制表符(相当于tab键)
\v 垂直制表符
\\ 反斜杠()
\' 单引号
\" 双引号
? 问号
\0oo 八进制值(oo必须是有效八进制数)
\xhh 十六进制值(hh必须是有效十六进制数)

通过一个例子更好的理解转义字符:

#include

int main(void)
{
    float salary;

    printf("\aEnter your desired monthly salary:");
    printf(" $_______\b\b\b\b\b\b\b");
    scanf("%f", &salary);
    printf("\n\t$%.2f a month is $%.2f a year.", salary, salary * 12.0);
    printf("\rGee!\n");
    return 0;
}

运行结果:

解析:

在程序的第7行 printf("\aEnter your desired monthly salary:"); 中的 \a 会发出警报的声音(能否发出警报取决于硬件,有可能不会发出警报)

接着第8行的 printf(" $_______\b\b\b\b\b\b\b"); 先将$_______打印出来呢,接着使用 \b 移动光标,使光标紧跟$符

在第10行的 printf("\n\t$%.2f a month is $%.2f a year.", salary, salary * 12.0); 首先是 \n 进行换行,接着是制表符 \t 使后面的内容缩进。光标停留在最后的点那里(.),如下图:

在第11行的 printf("\rGee!\n"); \r 将光标移动到当前行是起始位置,再打印内容,最后的 \n 换行

reference

《C Primer Plus》(第六版)

大话C语言变量和数据类型---C语言中文网

C语言转义字符---C语言中文网

C 数据类型---菜鸟教程

C 变量---菜鸟教程

C 常量---菜鸟教程

你可能感兴趣的:(c基础)