文章目录
初识C语言
1. 数据类型
char //字符数据类型
short //短整型
int //整型
long //长整型
long long //长长整型
float //单精度浮点型
double //双精度浮点型
- 计算每种类型大小如下:
printf("%d\n",sizeof(char));//printf是c语言编译器提供的库函数,使用需要包含头文件stdio.h
2. 常量、变量
1.常量
C语言中常量分为以下几种
- 字面常量
3.14;
'a';
const
修饰的常变量
const float pai=3.14;//这里pai为const修饰的常变量
pai=5//不可直接修改
const int n = 10;
int arr[n]={0};//n仍为变量,不可这样使用
- #define定义的标识符常量
#define MAX 100
printf("max = %d\n",MAX);
- 枚举常量
enum Sex
{
//枚举常量默认从0开始,依次向下递增1
MALE = 3,//也可赋初值进行改变
FEMALE,
SECRET
},
int main ()
{
enum Sex s = MALE;
printf("%d\n",MALE);
//略
return 0;
}
2.变量
2.1 变量的分类
- 局部变量
- 全局变量
include<stdio.h>
int global = 2019;//全局变量
int main()
{
int local = 2018;//局部变量
int global = 2020;
printf("%d\n",global);
return 9;
}
-
上面的局部变量global使用没有问题。
-
当局部变量和全局变量同名时优先使用全局变量。
2.2变量的作用域和生命周期
- 作用域
- 局部变量:定义在函数体内部的变量,作用域仅限于函数体内部,离开函数体就会失效,再调用会出错。
- 全局变量:所有的函数体外部定义的变量,它的作用域是整个程序,也就是所有源文件,包括.c和.h文件。
//当全局变量不在一个源文件中时,可用"extern"声明变量
int g_val = 2022;
extern int g_val;//另一个源文件中
- 生命周期
- 局部变量的生命周期: 进入作用域生命周期开始,到出作用域生命周期结束。
- 全局变量的生命周期: 整个程序的生命周期。
3. 字符串+转义字符+注释
1.字符串
#include<stdio.h>
int main() {
char arr1[] = { "bit" };
char arr2[] = { 'b','i','t' };//会打印出随机值
char arr3[] = { 'b','i','t','\0' };
printf("%s\n", arr1);
printf("%s\n", arr2);
printf("%s\n", arr3);
return 0;
}
字符串的结束标志是\0的转义字符,但在计算字符串长度时\0作为结束标志,不算做字符串内容
#include<stdio.h> #include<string> int main() { char arr1[] = { "bit" }; char arr2[] = { 'b','i','t' }; char arr3[] = { 'b','i','t','\0' }; printf("%d\n", strlen(arr1)); printf("%d\n", strlen(arr2)); printf("%d\n", strlen(arr3)); return 0; }
2.转义字符
转义字符 | 意义 |
---|---|
\’ | 用于表示字符常量’ |
\" | 用于表示一个字符串内部的双引号 |
\\ | 用于表示一个反斜杠,防止它被解释为为一个转义序列符 |
\a | 警告字符,蜂鸣 |
\b | 退格 ,将当前位置移到前一列 |
\f | 换页,将当前位置移到下页开头 |
\n | 换行 ,将当前位置移到下一行开头 |
\r | 回车 ,将当前位置移到本行开头 |
\t | 水平制表符,(一般相当于四个空格,或者 tab 键的功能) |
\v | 垂直制表符 |
\ddd | ddd表示1~3个八进制的数字,如:\130 X |
\xdd | dd表示2个十六进制的数字,如:\x30 0 |
#include <stdio.h>
int main (){
printf("%c\n",'\'');//用于打印'
printf("%s\n","\"");//用于打印”
return 0;
}
#include <stdio.h>
#include<string>
int main() {
printf("%d\n", strlen("abcdef"));
printf("%d\n",strlen("c:\test\628\test.c"));
return 0;
}
//结果依次为6、14
3.注释
- 代码中有不需要的部分可以直接注释掉,或删掉。
- 代码复杂的部分可以添加注释便于理解。
4.语句、函数
之后展开
5.数组
- C语言中数组的定义:一组相同类型元素的集合。
- C语言规定:数组的每一个元素都有下标,下表是从0开始的,且数组可以通过下标来访问。
6.操作符
先简单介绍
- 算术操作符
+ - * / % |
---|
- 位移操作符
>> << |
---|
位移操作符移动的是二进制位
#include<string>
int main() {
int a = 2;
int b = a<< 1;
printf("%d\n", b);
return 0;
}
//结果为4
- 位操作符
& ^ | |
---|
- 赋值操作符
= += -= *= /= &= ^= |
---|
- 单目操作符
! 逻辑反操作 |
---|
- 负值 |
+ 正值 |
& 取地址 |
sizeof 操作数的类型长度 |
~ 对一个数的二进制按位取反 |
– 前置或后置-- (前置–:先–,后使用,后置:先使用,后–) |
++ 前置或后置++ (同理) |
* 间接访问操作符(解引用操作符) |
( ) 强制类型转换 |
计算机中储存的的是补码,负数的反码为原码符号位不变其他位按位取反,补码为反码+1,正数的原码,反码,补码都相同。
#include<string> int main() { int a = 0;//计算机中存储的为0000...的补码即1111... printf("%d\n", ~a); return 0; }//~a为-1
//sizeof是一个操作符而不是函数,用于计算类型或者变量的大小,单位是字节(byte)
int main() {
int a = 10;
printf("%d\n", sizeof(int));
printf("%d\n", sizeof(a));
return 0;
//结果都为4
- 关系操作符
> >= < <= != == |
---|
- 逻辑操作符
&& || |
---|
- 条件操作符
exp1 ? exp2 : exp3 |
---|
- 逗号表达式
exp1, exp2, exp3, exp4 |
---|
int main() {
int a = 0;
int b = 3;
int c = 5;
int d = (a = b + 2, c = a - 4,b = c + 2);
printf("%d\n", d);
return 0;
//逗号表达式是从左向右依次计算,整个表达式的结果是最后一个表达式的结果,此处b=3
- 下标引用
[] () . -> |
---|
[]下标引用操作符,如数组arr[3],[]的操作数是arr和3,3[arr]也对但一般不这样写
()函数调用操作符,调用函数的时候,函数名后面使用的()就是函数调用操作符
7.常见关键字
auto double int struct break else long switch case enum register typedef char extern(声明外部符号) return union const float short unsigned continue for signed void default goto sizeof(是操作符不是函数) volatile do if static while
- typedef
typedef是类型定义,这里应该理解为类型重命名。
//将unsigned int重命名为uint_32,所以uint_32也是一个类型名
typedef unsigned int uint_32
int main()
{
//num1和num2这两个变量的类型是一样的
unsigned int num1 = 0;
uint_32 num2 = 0;
return 0;
}
- 关键字static
在c语言中:
static是用来修饰变量和函数的
- 修饰局部变量称为静态局部变量
- 修饰全局变量称为静态全局变量
- 修饰函数称为静态函数
#include<string>
void test()
{
int a = 1;//a是局部变量
a++;
printf("%d ", a);
}
int main() {
int i = 0;
while (i < 10)
{
test();//出作用域生命周期结束,每次循环都将a重置为1
i++;
}
return 0;
}
#include<string>
void test()
{
static int a = 1;
a++;
printf("%d ", a);
}
int main() {
int i = 0;
while (i < 10)
{
test();//static修饰a后每次循环a的值不再重置
i++;
}
return 0;
}
static修饰局部变量,改变了局部变量的生命周期,本质是改变了变量的存储类型。
全局变量、函数可以在其他源文件中使用,是因为其具有外部链接属性,但在static修饰之后,就变成了内部链接属性,所以static修饰全局变量或函数后,使得这个全局变量或函数只能在自己所在的源文件内部使用,不能在其他源文件中使用
栈区 1.局部变量 2.形参 3.函数返回值。数据的作用范围过了之后,系统就会回收自动管理栈区的内存。 堆区 由程序员调用 malloc()
函数来主动申请,需使用free()
函数来释放内存,若忘记释放内存,很容易造成内存泄漏。静态区 1.静态变量(包含static修饰的静态变量) 2.全局变量。 一旦静态区的内存被分配,静态区的内存直到程序全部结束后才会被释放。
- define定义常量和宏
#include <stdio.h>
//define 定义标识符常量
#define MAX 1000
//define 定义宏
#define ADD(x,y) x+y//将x+y代入运算
int main() {
int sum = ADD(2, 3);
printf("%d\n", sum);
sum = 10 * ADD(2, 3);
printf("%d\n", sum);//实际上是10*2+3,若想得出50需改为(x+y)
return 0;
}
8.指针
1. 内存
- 内存是如何编号的?
地址线(32位机器32根,64位机器64根)通电产生电信号,电信号在转换成数字信号,即1和0组成的二进制序列作为内存的编号。
以32位机器为例:共有232组二进制序列,因此对应232个内存单元。
00000000000000000000000000000000 00000000000000000000000000000001 … 11111111111111111111111111111111
- 一个这样的内存单元有多大空间?
假设一个内存单元为1
bit
,则所有内存单元4,294,967,296bit
= 536,870,912byte
= 524,288kb
= 512MB
= 0.5GB
,可以发现空间太小,而且1个char
就占了1byte
=8bit
造成空间浪费,因此实际上一个内存单元为1byte
变量是创建在内存中的(按内存分配空间),每个内存单元都有地址,所以变量也是有地址的,取出变量地址如下:
#include<stdio.h>
int main()
{
int num = 10;
#//取出num的地址
//这里num为4个字节,每个字节都有地址,取出的为第一个字节的地址(较小的地址)
printf("%p\n",&num);// %p是以地址形式打印
return 0;
}
地址的存储与指针变量的使用:
#include<stdio.h>
int main()
{
int a = 10;
int *pa = &a;//pa用来存放a的地址,在c语言中pa称为指针变量
//* 说明pa是指针变量,int说明pa执行的对象是int类型的
*pa = 20;//通过地址改变a的值
printf("%d\n", a);
return 0;
}
2. 指针变量的大小
#include<stdio.h>
//指针变量的大小取决于地址的大小
//32位平台下的地址是32个bit位(即4个字节)
//64位平台下的地址是64个bit位(即8个字节)
//sizeof计算的结构是无符号整数,对于的打印格式应该是:%zu
int main()
{
printf("%zu\n", sizeof(char*));
printf("%zu\n", sizeof(int*));
printf("%zu\n", sizeof(short*));
printf("%zu\n", sizeof(double*));
return 0;
}
9.结构体
#include<stdio.h>
struct Stu
{
char name[20];//名字
int age; //年龄
char sex[5]; //性别
float score; //成绩(出现小数时,编译器默认时double类型,如果希望时float类型,应该加上f)
};
int main()
{
struct Stu s = { "张三",20,"男",87.5f };//结构体的创建与初始化
//若要输入数据到s中
scanf("%s %d %s %f",s.name,&(s.age),s.sex,&(s.score));//数组名表示首地址
//访问结构体成员的三种方式
printf("name = %s age = %d sex = %s id = %d\n", s.name, s.age, s.sex, s.id);// .为结构成员访问操作符
struct Stu* ps = &s;
printf("name = %s age = %d sex = %s id = %d\n", ps->name, ps->age, ps->sex, ps->id);// ->操作符
printf("name = %s age = %d sex = %s id = %d\n", (*ps).name, (*ps).age, (*ps).sex, (*ps).id);
return 0;
}