一、认识C语言
(一)第一个c语言代码
首先写下第一个C语言代码吧。
#include <stdio.h>//这里需要介绍一下.c .h 这两种文件后缀,分别为源文件和头文件
//在我们创建一个写代码的文件时,创建的.c文件是源文件;
//由于我们后续使用的printf函数,我们需要在主函数前引用《stdio>.h文件,
int main()//main函数-主函数
{
printf("I can do it!");//用于打印输出显示在屏幕上的内容
return 0;//与main函数前的int对应
}//注意这个花括号的存在。
现在让我们来分析一下这段代码吧。
首先简单介绍一下 // 可以作为注释在代码中标注,为我们敲下的代码做一个简单的介绍和备注。注释的类型有两类,一类是C语言中的/**/,一类是C++语言中的//。同时//也可以在C语言中使用。
(二)main函数
- main函数是程序的入口
- main函数有且只有一个
- 即使一个项目中有多个.c文件,但只能有一个main函数(因为程序的入口只有一个)
main函数也被称为:主函数。main前面的int表示main函数执行结束的时候返回一个整型类型的值,因此与main函数后面的return 0相对应。
(三)printf函数
介绍了程序中的第一个函数,现在来简单介绍一下第二个函数吧。
1.printf()的作用
printf()的作用是将参数文本输出到屏幕。它名字里面的f代表format (格式化) ,表示可以定制输出文本的格式。
2.printf()的头文件
printf函数,是一种库函数,什么是库函数?先简单理解为为了方便使用,将常使用的代码通过C语言标准来规定了一组函数,这些函数被组成一个函数库,也就是标准库。额外了解不同的编译厂商函数对应的代码可能存在差异。
同类型的库函数一般会声明在同一个头文件中,所以在使用库函数时,先与对应的标准库打个招呼,因此打招呼的过程也叫引用头文件的过程。
printf对应的头文件是stdio→std:标准的;i:input,输入;o:output,输出。引用头文件就写作为 #include <stdio.h> 。
3.printf()的占位符
#include <stdio.h>
int main()
{
int a = 0;
scanf("%d", &a);
printf("It's %d o'clock.", a);
return 0;
}
printf()参数与占位符是一一对应关系,如果有n个占位符,printf()的参数就应该有n+1个。如果参数个数少于对应的占位符,printf()可能输出内存中的任意值。
printf()占位符为%d时
- %5d表示这个占位符的宽度至少为5位。如果不满5位,对应的值的前面会添加空格。
- 输出的值默认是右对齐;如想左对齐,可在%后插入-号。
#include <stdio.h>
int main()
{
int a = 1234;
int b = 356467866;
printf("%5d\n", a);
printf("%-5d\n", a);
printf("%d\n", b);
return 0;
}
printf()占位符为%f时
- 输出小数时,希望小数点后面只保留两位,占位符可以写成%.2f或%0.2f;
- %5.2f 表示输出字符串宽度为5,小数位数为2;
- 默认是右对齐,所以如果数字不足位,空位会以空格显示在字符串头部;
printf显示正负号
printf()不对正数显示+号,只对负数显示-号。如果想让正数也输出+号,可以在占位符的%后面加一个+。
4.printf()的具体代码格式
代码 | 格式 | 代码 | 格式 |
---|---|---|---|
%c | 字符 | %p | 一个指针 |
%d | 带符号整数 (十进制) | %% | 一个%符号 |
%f | 浮点数 | %e | 使用科学计数法的浮点数,指数部分的e为小写 |
%s | 一串字符 | %E | 使用科学计数法的浮点数,指数部分的E为大写 |
%u | 无符号整数 | %i | 整数,基本等同于%d |
%x | 无符号十六进制数, 用小写字母 | %a | 十六进制浮点数, 字母输出为小写 |
%X | 无符号十六进制数, 用大写字母 | %A | 十六进制浮点数, 字母输出为大写 |
(四)关键字
- 关键字都有特殊的意义,是保留给C语言使用的;
- 创建标识符(命名变量)时,不能与关键字重复;
- 关键字是规定好的,无法自己创建。
关键字又称保留字,如(不用刻意去背诵,后续使用时会慢慢熟悉了解)
auto | const | double | float | int | short | struct | unsigned |
---|---|---|---|---|---|---|---|
break | continue | else | for | long | signed | switch | void |
case | default | enum | goto | register | sizeof | typedef | volatile |
char | do | extern | if | return | static | union | while |
在C99标准中加入了inline、restrict、_Bool、_Complex、_Imaginary等关键字。
(五)字符和字符串
1.字符和ASCII编码
字符是在键盘上可以敲出的各种字符,比如a,b,#,&等。在C语言中字符是用单引号(英)括起来的。如’a’,‘@’,‘&’。字符的打印使用%c。
计算机中所有的数据都是以二进制的形式存储的,那这些字符在内存中分别以什么样的二进制存储的呢?美国国家标准学会(ANSI) 出台了一个标准ASCII编码,C语言中的字符就遵循了ASCII编码的方式。
- 字符A-Z的ASCII码值从65~90;
- 字符a-z的ASCII码值从97~122;
- 对应的大小写字符(a和A)的ASCII码值的差值是32;
- 数字字符0-9的ASCII码值从48~57;
- 换行\n的ASCI值是: 10;
- 在这些字符中ASCII码值从0~31这32个字符是不可打印字符,无法打印在屏幕上观察。
#include <stdio.h>
int main()
{
printf("%c\n",97);//输出为a
printf("%d\n",'A');//输出为65
return 0;
}
2.字符串
C语言中使用双引号(英)括起一串字符,如"abcd".
- 字符串的打印使用%s;
- 字符串中末尾隐藏着一个\0,是字符串的结束标志;
- 在使用库函数printf()打印字符串或strlen()计算字符串长度时,遇到\0的时候就自动停止了,不将\0计入其中。
#include <stdio.h>
int main()
{
char arr1[] = {'a','b','c'};//注意字符和字符串时使用char
char arr2[] = {"abc"};
printf("%s\n%s",arr1,arr2);
return 0;
}
输出结果:
为什么arr1输出的结果后续有乱码呢?
上面提到\0是printf()在打印时遇到\0就会停止,所以得到arr1中的\0是不明位置的,知道程序读到时输出的乱码才会停下来。所以输出字符串时应注意arr1这样例子的使用,应在后加上’\0’。注意\0的重要性。
3.转义字符
那么现在让我们了解一下上面提到的\0和\n吧。
转义字符,转变原来的意思的字符。
- ?:在书写连续多个问号时使用,防止他们被解析成三字母词,在新的编译器上没法验证了。
- ‘:用于表示字符常量’
- ":用于表示一个字符串内部的双引号
- \:用于表示一个反斜杠,防止它被解释为一个转义序列符
- \a:警报,这会使得终端发出警报声或出现闪烁,或者两者同时发生
- \b:退格键,光标回退一个字符,但不删除字符
- \f:换页符,光标移到下一页。在现代系统上,这已经反映不出来了,行为改成类似于\v
- \n:换行符
- \r:回车符,光标移到同一行的开头
- \t:水平制表符。通常为4或8个字节,可修改
- \v:垂直分隔符,光标移到下一个垂直制表位,通常为下一行的同一列
- \ddd:ddd表示1~3个八进制的数字 如:\130 表示字符X
- \xdd:dd表示2个十六进制数字 如:\x30 表示字符0
- \0:null字符,代表没有内容,\0就是\ddd这类转义字符的一种,用于字符串的结束标志,其ASCII码指是0
(六)常量
常量是指在程序运行过程中,其值不发生变化的量。常量又分类为如图所示。
(七)变量(标识符)
1.变量
变量代表内存中具有特定属性的一个存储单元,它用来存放数据,即变量的值。这些值在程序的执行过程中是可以改变的.
变量名实际上以一个名字代表一个对应的存储单元地址。编译、链接程序时,由编译系统为每个变量名分配对应的内存地址(就是空间)。从变量中取值实际上是通过变量名找到内存中存储单元的地址,并从该存储单元中读取数据。
2.变量的命名
变量的命名规定如下: C语言规定标识符只能由字母、数字和下划线三种字符组成,并且第一个字符必须为字母或下画线。
编译系统认为大写字母和小写字母是不同的字符,因此C语言要求对所有用到的变量做强制定义,即“先定义,后使用”。同时在选择变量名和其他标识符时,应尽量做到“ 见名知意”,即选择具有含义的英文单词(或其缩写)作为标识符。注意,变量名不能与关键字同名!
3.变量类型
●全局变量:在大括号外部定义的变量就是全局变量
全局变量的使用范围更广,整个工程中想使用,都是有办法使用的。
●局部变量:在大括号内部定义的变量就是局部变量
局部变量的使用范围是比较局限,只能在自己所在的局部范围内使用的。
#include <stdio.h>
int a = 1000;
int main()
{
int a = 100;
printf("%d\n", a);
return 0;
}
当全局变量和局部变量名字一致时,以局部变量的值优先使用。
4.变量初始化
如int a = 1000;或int a = 100;都是对变量a的初始化。
如不对a初始化,它们的值分别为什么?
从下图可以看到当全局变量未初始化时,值为0;但局部变量未初始化时,值不确定。
5.全局变量和局部变量在内存中存储在哪里呢?
一般我们在学习C/C++语言的时候,我们会关注内存中的三个区域:栈区、堆区、静态区。
- 1.局部变量是放在内存的栈区
- 2.全局变量是放在内存的静态区
- 3.堆区是用来动态内存管理的(后期会介绍)
二、数据类型
(一)数据类型分类
整型:
short [int] 短整型 signed short [int]-有符号的 unsigned short [int]
int 整型
long 长整型
long long 更长的整型
浮点型:
float 单精度浮点型、double 双精度浮点型、long double
字符型:
char、signed char–有符号的、unsigned char–无符号的
(二)signed和unsigned
C语言使用signed和unsigned关键字修饰 字符型和整型类型的。
signed关键字,表示该类型不带有正负号,包括负值;
unsigned关键字,表示该类型不带有正负号,只能表示零和正整数。
对于int类型,默认是带有正负号的,也就是说int等同于signed int。由于这是默认情况,关键字signed一般都省略不写,但是写了也不算错。
int类型也可以不带正负号,只表示非负整数。这时就必须使用关键字unsigned声明变量。整数变量声明为unsi gned的好处是,同样长度的内存能够表示的最大整数值,增大了一倍。比如,16位的signed short int 的取值范围是: -32768~32767, 最大是32767;而unsigned short int 的取值范围是: 0~65535, 最大值增大到了65,535。
字符类型char也可以设置signed和unsigned。
signed char c;//范围为-128到127
unsigned char c;//范围为0到255
(三)补充:布尔类型(了解即可)
C语言中,用整数0来表示假,非零值表示真。
在C99中也引入布尔类型_Bool,是专门表示真假的。布尔类型的使用包括头文件<stdbool.h>,布尔类型变量的取值是true和false.
#include <stdio.h>
#include <stdbool.h>
int main()
{
_Bool flag = true;
if (flag)
{
printf("I can do it");
}
return 0;
}
三、数据类型的长度
(一)sizeof操作符
- sizeof是一个关键字,也是操作符,用来计算操作符的类型长度,单位是字节;
- sizeof操作符的操作数可以是类型,也可是变量或者表达式;
- sizeof的操作数如果不是类型,是表达式的时候,可以省略后边的括号;
- sizeof后边的表达式是不真实参与运算的,根据表达式的类型来得出大小;
- sizeof的计算结果是size_t类型的。因为sizeof的返回值类型在不同系统中可能不同,所以统一为size_t类型。
(二)数据类型长度
#include <stdio.h>
int main()
{
printf("%zd\n", sizeof(char));
printf("%zd\n", sizeof(_Bool));
printf("%zd\n", sizeof(short));
printf("%zd\n", sizeof(int));
printf("%zd\n", sizeof(long));
printf("%zd\n", sizeof(long long));
printf("%zd\n", sizeof(float));
printf("%zd\n", sizeof(double));
printf("%zd\n", sizeof(long double));
return 0;
}
(三)sizeof中表达式不会执行
#include <stdio.h>
int main()
{
short s = 2;
int b = 10;
printf("%d\n",sizeof(s = b+1));
printf("s = %d\n",s);
return 0;
}
由上述结果可以看到s的值没有发生改变,所以sizeof 中的表达式不会执行。