目录
变量
1.变量定义的方法
int age = 150;
float weight = 45.5f;
char ch = 'w';
是数据类型加上命名英语来定义变量,这里一个好的习惯就是进行赋值。
2.变量的命名
有几点注意事项
1.只能由字母(包括大写和小写)、数字和下划线( _ )组成。
2.不能以数字开头。
3.长度不能超过 63 个字符。
4.变量名中区分大小写的。
5 .变量名不能使用关键字。
3.变量的分类
(1)全局变量 (2)局部变量
定义在主函数main外 定义在主函数main内
作用域是作用于整个工程 作用域是变量所在的局部范围
生命周期是整个程序的生命 生命周期是进入范围开始出范围结束
下面说几个容易犯错的地方
a:当局部变量与全局变量发生冲突时——就近原则
#include<stdio.h>
int a = 10;
int main()
{
int a = 20;
printf("%d", a);
return 0;
}
结果打印出来 a = 20
这里提一个建议:尽量少使用全局变量,哪里使用放哪里,避免他俩发生冲突。
b:局部变量的作用域是变量所在的局部范围
int main()
{
{
int a = 1;
}
printf("%d", a);
return 0;
}
这里就会报错,也就是说,a出了他的大括号后会被报错,他的作用域就是他所属的大括号。
c:局部变量的生命周期
int main()
{
{
int a = 10;
printf("1: %d\n", a);
}
printf("2: %d\n", a);
return 0;
}
a的生命周期仅仅在内层的大括号里面,所以第一个printf可以正常打印,但第二个会报错。
d:全局变量作用于整个工程,所以必须有定义和声明
这里是作用于整个工程,在函数前定义,一个源文件里面需要给定义打个招呼就是声明。
#include<stdio.h>
int g_a;//这里就是声明
void test()
{
printf("test:%d\n", g_a);
}
int main()
{
printf("%d\n", g_a);
test();//调用函数
return 0;
}
对比上面和下面,能明显发现问题,定义 g_a地方不同,声名变量放在了使用后面,这是一个经典的因果倒置错误,我们的代码首先是先经过程序编译以后才会运行的,在编译的时候,我们的代码在test函数中的g_a还没有声名,就已经被使用,所以在此处产生了编译错误。
#include<stdio.h>
void test()
{
printf("test:%d\n", g_a);
}
int g_a = 2022;//定义
int main()
{
printf("%d\n", g_a);
test();//调用函数
return 0;
}
再来对比这个,在下面的这段代码中也产生了一个很严重的问题,因为有一个printf不在任何一个函数里面,在运行的过程中根本运行不到他上面,这就自然编译器会报错了。
#include<stdio.h>
int g_a = 2022;//定义
void test()
{
printf("test:%d\n", g_a);
}
int g_a = 2022;//定义
printf("%d", g_a);
int main()
{
printf("%d\n", g_a);
test();//调用函数
return 0;
}
说了很多的定义和声明,大家可能迷惑到底什么是声明什么是定义。
我们这里给出一段代码,来区分一下,也是对面上面这三个差不多的代码。
int g_a;//声明
void test()
{
printf("test:%d\n", g_a);
}
int g_a = 2022;//定义
int main()
{
printf("%d\n", g_a);
test();//调用函数
return 0;
}
在这段代码中,我们直接对其进行int g_a=2022时,也就是第七行,此时称作定义。无论这个定义在前排还是靠后的位置,都称作定义,但是有可能会出现一个问题,我的变量定义在使用的后面了,这个时候编译器就会直接报错。那么为了处理这种情况,我们在第一行补上一个int g_a,但是没有给其赋值,此时,称作声明,也就是为了防止我的编译器报错,我先声明一下,我有这个变量,然后后面在对其定义。当然我也可以将定义放在第一行,此时的定义就等同于声名了。
而这些都是在同一个源文件里的全局变量的声明和定义,如果在两个源文件里,我们又该如何定义和声明呢。
第一个源文件
#define _CRT_SECURE_NO_WARNINGS 1
int a = 0 ;
第二个源文件
extern int g_a;
int main() //也是对引用的打个招呼,一个源文件里面声明后用,
{ //不是一个源文件就用extern来打招呼
printf("%d\n", g_a);
return 0;
}
extern——这个关键词可以声明同一个工程项目中的外部变量,意思就是在一个源文件里的,我们在第二个源文件里想要使用的时候,需要用 extern 来进行声明。
4.变量的使用
在定义后,直接进行引用,用在输入和输出后。
#include<stdio.h>
int main()
{
int num1 = 0;
int num2 = 0;
int sum = 0;
scanf("%d %d", &num1, &num2);
sum = num1 + num2;
printf("%d", sum);
return 0;
}
要注意好习惯的养成——给变量赋值。
常量
1.常量的分类
我们将变量分为以下四种:
1.字面常量
2.const修饰的常变量
3.#define修饰的标识符常量
4.枚举常量
2.字面常量
#include<stdio.h>
int main()
{
//1 整数字面常量
//300 整数字面常量
//3.14 浮点数字面常量
//'a' 字符字面常量
//"abcjdksa" 字符串字面常量
return 0;
}
3.const修饰的常变量
常变量是个什么意思呢,就是在变量前加上一个 const 使其变量带有常量的性质,但是本质还是变量。
#include<stdio.h>
int main()
{
const int num =100 ;
num = 200;
return 0;
}
结果是报错,不能再给常量赋一个新的值。
在数组中也能证明
int arr[]
//可以不给定义多大数组,但是里面需要是常量,也必须要在后面赋值声明。
//所以const定义的常变量也不能给数组定义大小。
const int n = 10;
nt arr[n] = {0};
//会报错
但是在后面学习数组的时候会发现,有时候数组里面也放了变量,这个可能是打印数组里面的元素,而变量是其对应的下标,后面会慢慢介绍。
4.#define修饰的标识符常量
#define M 100
int main() //用define定义的就是常量,标识符常量,也可以放{}里面。
{
int arr[M] = { 0 };
printf("%d\n", M);
return 0; //这个M更改不了
}
这个时候 #define 修饰的M可以放在数组中,证明是个常量。小细节后面不加分号哦!!!
5.枚举常量
这个意思是一个一个列举出来,有很多例子,颜色、性别、血型等等。
枚举的标识符是enum
#include<stdio.h>
enum Color {
RED,//0
GREEN,//1
BLUE//2
//RED,GREEN,BLUE是枚举类型Color的可能取值,同时也是常量,所以叫枚举常量
};
int main()
{
enum Color c = BLUE;
printf("%d\n", RED);
printf("%d\n", GREEN);
printf("%d\n", BLUE);
printf("%d", c);
}
因为用整型打印出来,所以三个值分别是1,2,3。
字符串
1.定义
"hello world.\n"
形如这种由双引号引起来的一串字符称为字符串字面值,或者简称字符串
特别注意: %s - 打印字符串,打印到\0才停止,\0不算为字符串内容,后面慢慢解释
2.字符串在数组中的存放
int main()
{
char ch1[] = {'a', 'b', 'c'};
char ch2[] = "abc";
printf("%s\n", ch1);
printf("%s\n", ch2);
return 0;
}
第一个数组打印的是 abc 后面一大堆不知道的文字
第二个数组打印的只有 abc
是因为字符串在打印的时候,从起始开始到后面的\0结束,
而ch1没有\0,所以后面不知道什么时候结束,会出现奇怪的文字,
而第二个数组,字符串隐含包括\0,所以会打印出来 abc ,
我们监视来看一下
所以在数组 ch1 后加上\0 效果就一样了。
3.字符串的长度
c语言中提供了一个库函数,叫做strlen,这个函数可以计算字符串的长度,统计的是\0之前的字符个数。strlen------string lenth ,属于string这个库中。但是需要头文件#include <string.h> 来引用。
#include<stdio.h>
int main()
{
char arr1[] = "abc";
char arr2[] = { 'a','b','c' };
printf("%d\n", strlen(arr1));
printf("%d\n", strlen(arr2));
}
运行结果为
原因也是一样,第一个数组默认有 \0 所以是3,第二个数组没有 \0 不知道什么时候结束。
4.转义字符
(1)引入
#include<stdio.h> #include<stdio.h>
int main() int main()
{ {
printf("abcdtf"); printf("abcd\tf");
return 0; return 0;
} }
打印结果分别是 abcdtf abcdf
这时候我们发现,加上 \ 的 t 没有了原来的意思,而产生新的效果,这就是转义符。
(2)常见的转义符
转义字符 | 意思 |
\? | 在书写连续多个问号时使用,防止他们被解析成三字母词 |
\' | 用于表示字符常量' |
\" | 用于表示一个字符串内部的双引号 |
\\ | 用于表示一个反斜杠,防止它被解释为一个转义序列符 |
\a | 警告字符,蜂鸣 |
\b | 退格符 |
\f | 进纸符 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ddd | ddd表示1~3个八进制的数字。如\130X |
\xdd | dd表示2个十六进制的数字。如\x30 0 |
(1)分析常见的
这个转义字符,主要是避免三字母词使用的,那什么是三字母词呢。这里给出一段代码。
int main()
{
// ??) - 三字母词 - ]
printf("(are you ok??)");
return 0;
}
在一些编译器上会将??)这个转变成 ] 这个字符
为了避免这种情况,我们可以使用\?这个转义字符
int main()
{
// ??) - 三字母词 - ]
printf("(are you ok\?\?)");
return 0;
}
这样不会让 ? 出现错误,还有 \' \" \\ 都是一样的效果。
#include<stdio.h>
int main()
{
//printf("%c\n", ''');
printf("%c\n", '\'');
//printf("%c\n", '"');
printf("%c\n", '\"');
return 0;
}
(2)\ddd \xdd
这两个转移字符跟其他的转义字符有些区别
\ddd这个转义字符中,他会将后面的1~3个八进制数字先转换成十进制数字,然后在ASCII表中找到对应的字符。这个字符就是最终的结果
\xdd这个转义字符也是将后面的2个十六进制数先转换成十进制数,然后在ASCII表中找出对应的字符。这个字符就是最终的结果。
#include<stdio.h>
int main()
{
printf("%c\n", '\073');//073是8进制数字
printf("%c\n", '\x46');//x46是16进制数字
return 0;
}
是 %c 字符打印,换算后,再根据 ASCII表 进行赋值。
ASCII表
(3)很好的解释ASCII表
#include<stdio.h>
int main()
{
printf("%d\n", 100);
printf("%c\n", 100);
return 0;
}
这说明了100这个数字在数字中和字符中的不同表现形式
(4)数数到底几个字符
#include <stdio.h>
#include <string.h>
int main()
{
printf("%d\n", strlen("abcdef"));
printf("%d\n", strlen("c:\test\628\test.c"));
printf("%d\n", strlen("c:\\test\\628\\test.c"));
printf("%d\n", strlen("abc\qdef"));
return 0;
}
第一个 printf 是6个字符
第二个 printf 是14个字符,转义的字符为一个
第三个 printf 才是正确打印这个 c:\code\test.c
第四个 printf 是7个字符,虽然 \q 没有转义的意思,但是编译器自动识别为转义。
(5)字符 ‘ 0 ’ ,数字 0 ,字符 ‘ \0 ’ 的区别
' 0 ' 的ASCII值为48
0 和 ' \0 ' 本质一样,只是同一种东西的不同表现形式, 0 是数字形式,' \0 ' 是字符形式
比如下面这段代码中
int main()
{
char arr[] = { 'a', 'b', 'c' ,0};
printf("%s\n", arr);
return 0;
}
运行结果
所以 ‘ \0 ’ 是转义也是 0。
注释
1.C语言中
常用 /* 注释内容 */
2.C++中
常用 //注释内容
结束语
今天的学习就到这里了,大家加油,明天继续分享第三节。