C语言学习

C语言基础

  • 一、 什么是C语言
  • 二、优缺点
      • 1、优点
      • 2、缺点
  • 三、开发软件
      • 1、[Devcpp](https://bloodshed-dev-c.en.softonic.com/)
      • 2、[VScode](https://code.visualstudio.com/)和[Visual Studio](https://visualstudio.microsoft.com/zh-hans/vs/)
      • 3、[CLion](https://www.jetbrains.com/zh-cn/)
  • 四、程序结构
      • 1、C语言程序
      • 2、实现代码
  • 五、基本语法
      • 1、头文件
        • (1)为什么使用头文件
        • (2)引入头文件
      • 2、标准输入输出函数
        • (1)scanf
        • (2)printf
      • 3、格式化
        • (1)格式化符号
        • (2)例题
      • 4、数据类型
        • (1)整数类型
        • (2)浮点类型
        • (3)void类型
      • 5、变量
        • (1)变量的[命名规范](https://www.cnblogs.com/wfwenchao/p/5209197.html)
        • (2)声明
      • 6、强制转换
      • 7、左值右值
      • 8、常量
        • (1)数值常量
        • (2)define常量(文本的替换)
        • (3)const关键字(不可变变量)
        • (4)通过const修改指针
      • 9、存储类
        • (1)auto(默认存储类)
        • (2)static(静态存储类)
        • (3)[register](https://www.cnblogs.com/kingqinwang/p/5097335.html)
        • (4)extern
      • 10、运算符
        • (1)算数运算
        • (2)关系运算
        • (3)逻辑运算
        • (4)位运算
        • (5)其他运算符
        • (6)运算符优先级
      • 11、条件判断
      • (1)if判断
        • (2)三目运算符
      • 12、循环语句
        • (1)for 循环
        • (2)while循环(只有条件判断和逻辑结构)
        • (3)do……while循环
        • (4)循环控制
      • 13、数组
        • (1)数组
        • (2)初始化
      • 14、函数
        • (1)作用域
        • (2)函数是什么
        • (3)为什么使用函数
        • (4)函数的语法
        • (5)函数的声明
        • (6)函数的定义
      • 15、指针
        • (1)指针的概念
        • (2)指针的形式
        • (3)指针的相关信息
        • (4)在函数的形参使用指针
  • 更新中……
        • (5)指针的算数运算
        • (6)二级指针
        • (7)指针的和数组对比
        • (8)拓展
      • 16、内存管理
        • (1)内存分区
        • (2)malloc
      • 17、结构体
        • (1)什么是结构体
      • 18、文件IO
        • (1)文件的概念
        • (2)文件的打开和关闭
        • (3)文件的读和写


一、 什么是C语言

  1. C 语⾔是⼀种通⽤的⾼级语⾔,最初是由丹尼斯·⾥奇在⻉尔实验室为开发 UNIX 操作系统⽽设计的。C 语⾔最开始是于 1972 年在
  2. DEC PDP-11 计算机上被⾸次实现。 在 1978 年,布莱恩·柯林汉(Brian Kernighan和丹尼斯·⾥奇(DennisRitchie)制作了 C 的第公开可⽤的描述,现在被称为 K&R 标准。
  3. UNIX 操作系统,C编译器,和⼏乎所有的 UNIX应⽤程序都是⽤ C 语⾔编写的。由于各种原因,C 语⾔现在已经成为⼀种⼴泛使⽤的专业语⾔。

二、优缺点

1、优点

①易于学习
②结构化语言
③产生高效率的程序
④可以处理底层的活动
⑤可以在多种计算机平台上编译

2、缺点

C语言给编写者的权限大


三、开发软件

1、Devcpp

2、VScode和Visual Studio

3、CLion


四、程序结构

1、C语言程序

  • 预处理指令
  • 函数
  • 变量
  • 逻辑代码
  • 注释

2、实现代码

// 头文件 
# include 
// 主函数 
int main()
{
	//输出语句 调用printf库函数 
	printf("hello world!");
	return 0;
}

解释
① 第一行就是一个注释语句,可以使用多行注释/* */
②第二行就是一个预处理指令,头文件
③第四行开始到最后一行是一个标准函数,也叫主函数,C语言只能有一个main函数
④第六行是一个这输出语句使用printf函数


五、基本语法

1、头文件

(1)为什么使用头文件

头文件里有我们编写程序需要的一些基本函数,如输入scanf输出printf,这些函数已经有人帮我们写好,所以只需要引入头文件来使用库函数

(2)引入头文件

① 语法:
使用#include指令,头文件的引入是预处理语句

#include
#include"xxx.h"

②常用的头文件

头文件 变描述
#include 标准的输出头文件
#include 数函数
#include 字符串函数
#include 时间函数
#include 工具函数

注意:
头文件详情

2、标准输入输出函数

(1)scanf

①scanf 的声明

int scanf(const char *format,)

②括号里的参数
(“<格式化字符串>”,<参量表>);
(“%d”,&a);
解释
%d表示输入类型是一个int,还有==%c、%lf、%lld==标准化输出格式

(2)printf

① printf的声明

int printf(const char *format,)

②参数
(“<格式化字符串>”,<参量表>);
(“%d\n”,&a);

解释
\是转义符

3、格式化

(1)格式化符号

C语言学习_第1张图片

(2)例题

例题1:如果有⼀个题⽬是这样的,要求你输⼊⼀个 name+(数字),然后把数字输出出来,如果学过字符串处理的同学,应该就会觉得那直接⼀个正则,或者把name去掉,然后输出,如果数字不大,我们使用scanf格式化输出

//头文件 
#include
//主函数 
int main() {
	//定义一个a变量 
	int a;
	//输入函数 
	scanf("name%d",&a);
	//输出函数 
	printf("%d\n",a);
	return 0;
}

例题2:输出一个时间08:01,有前置0,通过字符串的输出要麻烦得多,通过格式化输出

#include
//主函数 
int main(){
	//输出函数 
	printf("%02d:%02d",8,1);
	return 0;
} 

4、数据类型

C语言学习_第2张图片

(1)整数类型

类型 存储大小 值的范围
char(默认就是signed) 1字节 -128 ~ 127或者0 ~ 255
usigned char 1字节 0 ~ 255
signed char 1字节 -128 ~ 127
int 2或4字节 -32768到32767或-2147483648到2147483647
usigned int 2或4字节 0 ~ 65535 或者 0 ~ 42949967295
short 2字节 -32768 ~ 32767
unsigned short 2字节 0 ~ 65535
long 4字节 -2147483648 ~ 2147483647
usigend long 4字节 0 ~ 2147483647
long long 8字节 -9223372036854775808 ~ 9223372036854775807

(2)浮点类型

类型 存储大小 值范围 精度
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位有效位

注意:
使用sizeof 来获得一个类型或变量的大小

//头文件
#include
//主函数
int main(){
	printf("%d\n",sizeof(char));
	printf("%d\n",sizeof(int));
	printf("%d\n",sizeof(long));
	printf("%d\n",sizeof(double));
	return 0;
} 

结果:
C语言学习_第3张图片

(3)void类型

  1. 修饰函数,函数不需要返回一个值
  2. 修饰针,这种针可以通过强制转换来实现转换到任意数据类型

5、变量

(1)变量的命名规范

①变量必须是以字母或下划线开头,不能是数字
②变量名区分大小写
③不能使用C语言关键字
④变量名中不能有空格
⑤可以使用拼音 ,但是最好不用,

实例:

//定义一个int数据类型的变量temp
int temp;
//定义一个char数据类型的数据变量str
char str;
//定义一个double数据类型的数据变量num
double num;

注意
变量的定义就是告诉编辑器在何处创建变量的存储,以及入额创建变量的存储,变量指定一个数据类型,并包含该类型的一个或多个变量列表

//定义变量a、b、c、d四个变量都是整形
int a,b,c,d;
int e=10;

(2)声明

①使用关键字修饰

extern int a; //表示的其他文件以及定义过a这个变量,我们这里直接拿来使用

②函数声明

//没有返回类型的函数声明
void f(int a);

注意
声明和定义最主要的区别就是:定义创建了对象并为此对象分配了内存,而声明并未分配内存

6、强制转换

程序中 字节长度较高变量对字节长度较低的变量有一定的兼容性,相反则不是,因此很可能造成数据的溢出,或者是不同数据类型之间float和int,得到一个float值,想保存int值,这时候需要强制转换

#include
 
int main(){
	float a = 1.2223;
	int b = (int)a;
	printf("a=%f\tb = %d\n",a,b);
	return 0; 
}

结果:
C语言学习_第4张图片

7、左值右值

①左值(lvalue):指向内存位置的表达式,左值可以出现在赋值号的左边或者右边
②右值(rvalue):指的是存储在内存某些地址的数值。右值是不能对其进行赋值的表达式,也就是说,右值可以出现在赋值号的右边,但不能出现赋值好的左边

说明
变量是左值,可以出现赋值号的左边。数值型的字面是右值,因此不能被赋值,不能出现在赋值号的左变

int a = 10;
//a就是一个指向内存的变量也就是是左值,10是存储在内存的某个地址的数值
int a = 0;
a = a + 1;
printf("%d\n",a)

程序说明
声明一个int类型的变量a,然后再声明的时候给赋予了初值0,然后第二句让a = a +1,此时左边的a是一个变量(lvalue)右边a的值加1,也就是右边整个构成(rvalue)

8、常量

(1)数值常量

注意此数值常量非彼数值,我们此处所说的常量是单纯的一个值,如3是一个整形常量,0.3就是一个浮点常量,'c’字符常量 ,"ccc"字符串常量,一般数值常量用来初始化,这种常量不易维护。,⽐如说我们在⼀个程序
的很多地⽅都⽤了同⼀个常量那么如果你想修改这个常量的值,可能会⼀个⼀个的替换,有的同学可能想到了直接⽂件全局替换,但是这样做是有⻛险的,⽐如我的常量为1,我想把它替换为2,但是我可能有⼀些其他的常量是1开头的,⽐如12,那么就会造成数据紊乱,甚⾄有些变量⾥⾯也包含了1那么可能会导致编译出错,再退⼀步讲,编译没问题,程序的运⾏结果也不会和预期⼀样

(2)define常量(文本的替换)

//xxx都会被替换为yyy
#define xxx yyy
//x表示一个常量,它值为value是10
#define x 10
  • 可以用#define实现宏函数eg
#define max(a,b) (a>b?a:b)
  • #define是一个预处理指令,放在程序的顶部
  • #define 后面没有分号
  • 尽量少使用#define,代码多时这种常量就会存在⼀种潜在的危险->冲突(如果报错还好,没有报错那就难受了,⼤概率程序的运⾏结果和
    预期不同)

(3)const关键字(不可变变量)

//定义一个常量,a值为10
const int a = 10;
  • const修饰后不能更改
  • 可以通过指针修改const定义的常量

(4)通过const修改指针

  • const修饰指针指向的内容,则内容不可变,但能通过一个同数据类型的指针改变值
const int *a=10;//内容不可变
  • const修改指针,指针的值不可变
int a=10;
int* const b = &a;

解释
此时const修饰的是指针,那么指针指向的地址不可变,也就是b指向的地址不能变,但是*b可变

  • const修改指针并修饰的指针指向的内容,那么指针指向的地址和值都不可变
int a = 10;
const int* const b = &a;

9、存储类

(1)auto(默认存储类)

范围局部,一般不用管

(2)static(静态存储类)

生命周期是整个程序从开始到结束,但是它的作用域只是局部

#include
void f() {
static int a = 0;
a++;
printf("%d\n",a);
}
int main()
{
for(int i = 0;i < 5; ++i) {
f();
}
return 0;
}

以上代码使用gcc编译会报错:error: ‘for’ loop initial declarations are only allowed in C99 mode
note: use option -std=c99 or -std=gnu99 to compile your code

正确代码:

#include
void fun(){
	static int a=0;
	a++;
	printf("%d\n",a);
}
int main()
{
	int i;
	for( i = 0;i < 5; i++){
		fun();
	}
	return 0;
}

(3)register

**用来定义存储在寄存器中而不是RAM中的局部变量。这意味着最大尺寸等于寄存器的大小(通常是一个词),且能对它应用一元的“&”运算符(因为它没有内存位置)

(4)extern

用于提供一个全局变量的引用,全局变量对所有的程序文件都可见的当使用extern时,对于无法初始化的变量,会把变量名指向一个之前定义过的存储位置
当您有多个⽂件且定义了⼀个可以在其他⽂件中使⽤的全局变量或函数时,可以在其他⽂件中使⽤ extern 来得到已定义的变量或函数的引⽤。可以这么理解,extern 是⽤来在另⼀个⽂件中声明⼀个全局变量或函数。
总结⼀句话extern就是为了在多⽂件编程的时候直接取另外
⼀个⽂件的变量
关于extern,其实初学

10、运算符

(1)算数运算

运算符 描述 实例
+ 对两个数进行相加 a=1+2 =>3
- 相减 a=2-1 =>1
* 相乘 a=2*2 =>4
/ 相除 a=10/2
% 趋于 a= 10%3
++ 变量自增1 a=0;++a =>1
- - 变量自减 a=0;- -a =>a = -1

(2)关系运算

运算符 描述
== 检查两个操作数的值相等,相等为真
!= 检查两个操作数是否相等,不相等为真
> 左操作数大于右操作数,为真
< 左操作数小于右操作数,为真
>= 左操作数大于等于右操作数,为真
<= 左操作小于等于右操作数,为真

(3)逻辑运算

运算符 描述
&& 如果两个操作数都非零,为真
“双竖线” 两个操作数任意一个非零,为真
非运算符,取反

(4)位运算

以下的运算都是将数转化为二进制在计算,然后再转化为相应的进制

运算符 描述 实例
& 与运算,全一则一,否则为零 3 & 6 = 2
“单竖线” 或运算,有一则一,否则为零 3 & 6 = 7
^ 异或运算,不同唯一,相同为零 3 ^ 4 = 7
~ 取反运算,零一颠倒 ~4 = 3
<< 左移运算,效果等价十进制中乘2的n次方 5<<1 = 10
>> 右移运算,效果等价十进制中除2的n次方 5>>1 = 2

(5)其他运算符

运算符 描述 实例
sizeof 变量的大小 sizeof(a)将返回4,其中a为整数
& 返回变量的地址 &a;将给出变量的实际地址
* 指向一个变量 *a;将指向一个变量
?: 条件表达式 如果条件为真?则值为x:否则值为y

(6)运算符优先级

类别 运算符 结合性
后缀 ()、[ ]、-> 、++ 、- - 从左到右
一元 +、-、!、++、 - -、(type)*、&、sizeof 从右到左
乘除 *、/ 、% 从左到右
加减 +、- 从左到右
移位 <<、>> 从左到右
关系 <、<=、>、>=、 从左到右
相等 == 、!= 从左到右
位与and & 从左到右
位异或XOR ^ 从左到右
位或or 竖线 从左到右
逻辑与and && 从左到右
逻辑或or 双竖线 从左到右
条件 ?: 从左到右
赋值 =、+=、-=、*=、/=、%=>>=、<<= 、&=、^=、\竖线= 从左到右
逗号 从左到右

11、条件判断

(1)if判断

#include
int main(){
	int a=10;
	if(a > 10){
		printf("yes"); 
	}
	else{
		printf("no");
	}
	return 0;
}

多条件:

if(xxx) {
}
else if(xxx) {
}
else {
}

(2)三目运算符

action ? ans1:and2;

用if实现

if(action){
	ans1;
}
else {
	ans2;
}

解释
action表示逻辑判断值,ans1就表示判断为真执行的操作,ans2判断为假执行的操作

12、循环语句

(1)for 循环

①for循环的组成
初始化,条件判断,迭代更新,逻辑操作语句
②语法结构

for(初始化语句;条件判断;迭代更新){
	逻辑操作语句;
}

代码实例:

#include
int main(){
	int a=1;
	int i,n;
	scanf("%d",&n);
	for(i = 0;i<n;i++){
		if (a%2 == 1){
			a++;
		}
		else {
			a=a;
		}
	}
	printf("%d\n",a);
	return 0;
}

(2)while循环(只有条件判断和逻辑结构)

while(条件判断){
	逻辑判断语句;
}

代码实例:

int i = 0;
while(++i<10){
	//pass
}

解释
当条件不满足时跳出循环,判断为真继续循环,条件判断为假就跳出循环

(3)do……while循环

do……while在结构上也只有条件判断和逻辑操作
①语法结构

do{
	逻辑判断语句;
}while(条件判断)

解释
先进行一次操作,然后再判断是否继续循环

例子:
在一个文件中读取数据的时候,什么时候才算读完呢?一般的话文件会有一个结束符(EOF),那么使用do……while结构,先读,读完后判断是否是文件结束符,如果不是的话就继续循环

(4)循环控制

①循环嵌套
二层循环简单举例:

#incude<stdio.h>
int main(){
	int n;
	int i,j
	for(i=0;i<n;++i){
		for(j=0;j<n;++i){
		//op
		}
	}
	return 0;
}

②死循环
根据需求设置循环,大部分情况下我们应该避免死循环,出现死循环我们应该好好检查循环处的代码
③break和continue
两者都是跳出循环,break跳出整个剩下的循环,而continue只跳出当前循环,也就是说后面的循环,继续执行操作
④goto(一般不用)

#include
int main(){
	int i,j,k;
	for(i = 0;i < 10; ++i) {
		for(j = 0;j < 10; ++j) {
			for( k = 0;k < 10; ++k) {
				if(i + j + k == 12) {
					goto out;//我们找到我们想要的第一个答案就直接goto跳出三层循环,这个out只是一个代名词,随意更改,不过要和下面对应上
			}
		}
	}
}
out://跳出的地方
	printf("YES");
return 0;
}

13、数组

(1)数组

数组就是存储一个固定大小的相同类型元素的顺序集合,注意这个集合里面的元素类型都是一样的,我们可以通过数组名+下标的方式访问我们存储的数据

  • 数字的下标是从0开始到n-1结束
  • 数组的元素都是相同的类型
  • 数组可以不止一维
  • 数组的长度是固定的

####(1)声明数组

①语法:数组类型+数组名+数组大小
②代码

int a[10];

解释
声明一个10个int数据大小的数组,一个int 4个字节,那么这个数组要占40个字节,其他类型char、double或者结构体类型都可以这样声明

(2)初始化

  • 可以在声明的时候初始化
    举例:
int a[3]={0,1,2};
int b[3]={0};

解释
a数组的三个位置初始化0、1、2,b数组全部舒适化为0,如果定义的是全局数组,那么它会自动给你初始化为0,但是局部,不初始化们就会给你一个随机值

  • 在声明后初始化
    ①memset()函数初始化
//函数的声明
void *memset(void *str,int c,size_t n)

解释
第一个传的参数是一个void类型指针,也就是任何数据类型都可以,第二个是int类型的,也就是初始化的值,第三个参数是长度,也就是要初始化的字节数
举例:

#include
#include
int a[10];
int main(){
	memset(a,-1,sizeof a);
	printf("%d\n",a[0]);
	printf("%d\n",-1);
	return 0;
}

②循环初始化

#include
#include
int a[10];
int main(){
	int i;
	for(i=0;i<10;++i){
		a[i]=i;	
	}
	printf("%d\n",a[1]);
	return 0;
}

14、函数

(1)作用域

定义变量,我们一般是写在main的大括号里,当main函数运行完成后就会失效,一般来说体会不是很明显,因此我们就只使用main函数。

  • 在一个大括号里面定义的变量等东西就属于这样一个作用域,超出大括号变量等零时的的东西自动销毁(但是申请的空间不会销毁或者说static类型的不会销毁)
  • 大括号可以嵌套,也就是作用域有很多层,注意此时高一级的作用域能在低级的作用域中使用,如果低作用域有一个和高作用域相同的变量名,那么在使用低作用域使用该变量的时候,其实使用的是当前低作用域的变量值(隐藏变量)
  • 不在大括号里打的变量为全局变量,全局变量一般在程序的顶部,表示的是这个变量贯穿整个程序,不会消亡,但是注意全局变量是位于堆区的

(2)函数是什么

函数是完成程序中一部分小功能的子程序,或者说将一段完成一个任务的语句的一个整合

(3)为什么使用函数

  • 使用函数可以省去多次编写重复代码,可以减少代码的代码量
  • 提高程序的可读性,方便后续的维护升级

(4)函数的语法

(modified_type) return_type
function_name(paramter list){
	//function action
}

解释

  • modified_type(函数修饰词)
    ① static 、extern、inline等

satic修饰函数表示只在本文件访问,被其修饰的函数也成为内部函数,extern修饰的函数可以在别的文件中调用,被其修饰的函数成为外部函数,inline表示内敛函数,内联拓展是用来消除函数调用时的时间开销。通常用于频繁执行的函数,对于小内存空间的函数非常受益
注意
①递归函数不能定义为内联函数
②内联函数一般适合于不存在while和switch等复杂的结构且只有1~5条语句的小函数上,否则编译系统将该函数视为普通函数。
③内联函数只能先定义后使用,否则编译系统会把它认为是普通函数
④对于内联函数不能进行异常的接口声明

(5)函数的声明

int function(int a,int b);
int function(int ,int);

上面两种声明是等价的,我们在声明的时候其实没必要给出形参的名字,我们只需要明确给出数据类型以及函数的返回类型即可。

(6)函数的定义

举例:

#include
int function(int a, int b) {
	int c = a + b;
	printf("%d\n", c);
	return c;
}
int main() {
	function(12, 3);
	return 0;
}

以上是有返回值的情况,如果不需要返回值那么定义viod类型即可

15、指针

(1)指针的概念

简单来说就是存储地址的变量或常量

(2)指针的形式

数据类型 * 指针名
//举例
//指针类型为int *  指针指向的类型是int
int *a;
//指针类型为char * 指针指向的类型是char
char *b;
// 指针类型为float * 指针指向的类型是float
float *c;

注意
指针类型和指针指向的类型是不同的

(3)指针的相关信息

  • 在32位系统下一个指针的大小就是4个字节,64位系统下就是8字节
  • 计算机几乎所有的东西都有一个内存地址这样一个“唯一标识符”,可以通过地址访问到该地址上的值,或者是修改
  • 不是所有的地址我们都能访问,所以在使用指针的时候尽量不要访问不该访问的地方(像内核区)
  • “野”指针是很可怕的,所以在使用指针时候务必初始化
  • 指针也有算数运算
  • 指针和数组不一样

(4)在函数的形参使用指针

代码举例:

#include
void MySwap(int a, int b) {
	int temp = b;
	b = a;
	a = temp;
	printf("%d %d\n", a, b);

}
int main() {
	int a = 0, b = 10;
	printf("%d %d\n", a, b);
	MySwap(a, b);
	printf("%d %d\n", a, b);
	return 0;
}
#include

void MySwap(int *a, int *b) {
	int temp = *b;
	*b = *a;
	*a = temp;
	//printf("%d %d\n", a, b);
}

int main() {
	int a = 0, b = 10;
	printf("%d %d\n", a, b);
	MySwap(&a, &b);
	printf("%d %d\n", a, b);
	return 0;
}

更新中……

(5)指针的算数运算

(6)二级指针

(7)指针的和数组对比

(8)拓展

16、内存管理

(1)内存分区

(2)malloc

①函数的声明
②样例
③注意

17、结构体

(1)什么是结构体

18、文件IO

(1)文件的概念

(2)文件的打开和关闭

(3)文件的读和写


你可能感兴趣的:(C语言,c语言,学习,unix)