C语言于1969年至1973年间,为了移植与开发UNIX操作系统,由丹尼斯·里奇与肯·汤普逊,以B语言为基础,在贝尔实验室设计、开发出来。
介绍
- C是一种通用的、过程式编程编程语言,支持结构化编程、词法作用域和递归,使用静态类型系统,并且广泛用于系统软件与应用软件的开发
- 操作系统
- 设备驱动等
- C++、Java借鉴C开发
- C++、Java、Python(cpython)等编译器或解释器基于C语言开发
- C语音被称为编程之母
- 1989年,
ANSI(美国国家标准协会)发布第一个C语言标准ANSI X3.159-1989(简称C89),常称为ANSI C
优点
-
支持直接操作底层硬件
-
速度最快
-
应用广泛
-
程序是一系列对数据加工的指定
-
汇编语言:机器语言的字符化表示,每个汇编指令对应一个机器语言指令
-
编程语言:编排指令和数据的规则
-
编译器/解释器:将编程语言转化为机器语言指令
环境部署
- mac
brew install gcc开发工具
- CodeBlock
- Visual Studio
- vscode
- C/C++(ms-vscode.cpptools)
- C/C++ Runner(franneck94.c-cpp-runner)
hello world
C语言的入口函数为 main 函数
/*
hello world
*/
#include <stdio.h>
/* 函数定义 */
void say() {
printf("hello world");
}
int main() /* main 函数 */
{
say(); // 函数调用
return 0;
}
说明:
/* */注释#开头,预处理指令,由预处理器处理main的()表示函数的参数int表示函数的返回值类型
{}表示函数体;语句以分号结束
printf()输出到屏幕return 0;表示函数的返回值,函数结束时执行0返回给操作系统,表示正常结束;非0表示错误结束
编译
$ gcc helloworld.c -o helloworld
$ ./helloworld
hello world%基础元素
-
基本数据类型
int整形char字符型- 字符串:结尾带有
结束字符("\0")的字符数组 - 字符串中,通过某个字符是否等于
\0判断是否结束
- 字符串:结尾带有
float单精度浮点实数型double双精度浮点实数型shortlongunsigned intunsigned char
-
派生类型
- 数组:
int arr[]; int arr1[5];int arr[3] = {1, 2, 3};int arr[] = {1, 2, 3};
- 指针:
int *p; char *c;
- 数组:
-
变量:指定类型内存块的名称
- 定义:
类型名 变量名 [= 初始值];
- 定义:
-
32位编译器数据占用字节数
| char | short | int | long | float | double | 指针 |
|---|---|---|---|---|---|---|
| 1 | 2 | 4 | 4 | 4 | 8 | 4 |
- 64位编译器数据占用字节数
| char | short | int | long | float | double | 指针 |
|---|---|---|---|---|---|---|
| 1 | 2 | 4 | 8 | 4 | 8 | 8 |
操作符
- 算术运算符:
+、-、*、/、%、++、-- - 比较运算符:
>、<、>=、<=、!=- 比较结果:
1或0
- 比较结果:
- 逻辑运算符:与
&&、或||、非!- 比较结果:
1或0
- 比较结果:
- 符合运算符:
-=、+=、*=、%=、&=、|=、^=、~=- 比较结果:
1或0
- 比较结果:
函数
- 函数:一个命名的程序块,用来执行专门的任务
- 定义
/* 函数定义 */
返回值类型 函数名(形参类型1 形参1, 形参类型2 形参2)
{
函数体
return 返回值;
}
/* 函数调用 */
函数名(实参1, 实参2)流程控制
条件 if else
if (条件表达式1)
程序块1
else if (条件表达式2)
{
程序块2
}
else
程序块3选择 switch
switch (条件表达式1)
{
case 常量1:
程序块1
break;
case 常量2:
程序块2
break;
default:
程序块3
}循环 for
for(初始表达式; 条件表达式; 条件处理) {
程序块
}循环 while
while(表达式) {
程序块
}
// 或
do
程序块
while(表达式);编译指令
- 条件
#if、#elif、#else、#endif,作用:预处理器依据条件来判断保留或删除某段源代码
#if 表达式1
[ 组1]
[#elif 表达式2
[ 组2]]
...
[#elif 表达式n
[ 组n ]]
[#else
[ 组n+1 ]]
#endif
#if defined( xxx ) && defined( xxx )
/* ... */
#endif#ifdef、#ifndef测试宏是否被定义
#ifdef 标识符
#ifndef 标识符宏
- 宏定义:
#define NAME VALUE- 示例:
#define PI 3.14
- 示例:
- 作用
- 预处理器将程序中的 NAME 使用对应 VALUE 替换,便于理解,防止出错
- 提取程序中经常出现的参数,便于快速修改
#include <stdio.h>
#if 0
int main()
{
printf("0");
return 0;
}
#else
int main()
{
printf("1");
return 0;
}
#endif
常用库
stdio.h
标准输入输出头文件 stdio.h
printf输出到屏幕- 格式:
int printf("格式串", 参数1, 参数2, ...) - 转义字符
\n换行符\t水平制表符\v垂直制表符\\反斜杠\?问号\a响铃\'单引号%%百分号%
- 占位符
%cchar 类型%dint 类型%ffloat 类型%lfdouble 类型%s字符串类型%10s宽度 10,右对齐%-10s宽度 10,左对齐
- 格式:
sizeof()变量(对应的类型)占用内存的大小scanf()从键盘输入数据,float x; scanf("%s", &x);
math.h
sqrt()开方函数
string.h
strlen("xxx")获取字符串长度strcyp(x, "str")
指针
指针(pointer)本质是变量的地址,通过取地址运算符&获取一个变量的地址,如:&x指针变量:存储指针(地址)的变量类型 *是指针类型,用来存储类型变量的地址解引用运算符 *用来获取一个指针变量指向的变量
int x = 8, y = 8;
int *p = &x;
*p = 6;
b = *p;
int arr[] = {1, 2, 3};
int *p = arr; /* 等价于 int *p= &(arr[0]) */- 使用指针变量指向数组的某个元素
char ch, *p, crr[]={'h', 'e', 'l', 'l', 'o'}
p = &ch;
*p = 'x'; // ch is 'x'
p = crr;
*p = 'H'; // crr is {'H', 'e', 'l', 'l', 'o'}
*(p+2) = 'L'; // crr is {'H', 'e', 'L', 'l', 'o'}- 使用指针变量指向数组的某个元素
char *p, *q, crr[]={'h', 'e', 'l', 'l', 'o'}
p = crr;
*q = crr + 5;
while(p < q) {
printf("%c ", *p);
p++;
}- 指针传递
void swap(int *a, int *b) {
int tmp = *a;
*a = *b;
*b = tmp;
}
int main() {
int x = 3, y = 4;
swap(&x, &y);
printf("%d %d\n", x, y);
return 0;
}- 数组名本质是数组第一个元素的地址,因此数组作为函数变量传递时,本质为指针(地址)
struct
- struct 用来定义自定义数据类型
- 使用
成员访问符号(.)访问结构体的成员 - 结构体指针
struct 结构体名 * - 使用
访问运算符(->)访问结构体指针的成员
- 使用
/* 定义结构体 */
struct Student
{
char name[10];
int age;
floag score;
};
// 实例化
struct Student stu;
stu.age = 18;
strcpy(stu.name, "xianbin"); // strcpy 将常量复制到 stu.name 中
stu.score = 60;
// 结构体指针
struct Student *sp;
p = &stu;
(*p).age = 19;
strcpy((*p).name, "xiexianbin");
sp->score = 100;内存管理
malloc()在内存堆区分配一块内存空间realloc重新分配内存,并将旧内存地址中的内容复制到新的内存空间中free释放内存
int *p = (int *)malloc(3*sizeof(int));
*p = 1;
*(p+1) = 2;
p[2] = 3;
for(int i=0; i<3; i++)
printf("%d\t", p[i]); // p[]i eq *(p+1)
printf("\n");
// 重新分配内存
p = (int *)realloc(p, 6*sizeof(int));
// 释放内存
free(p);文件读写
// 打开文件
File *fopen("文件路径", "打开模式");
// 关闭文件
int fclose(FILE *文件指针);
// 返回值大于0,读入的个数;返回值小于等于,则读入失败
int fscanf(FILE *fp, const char *format, ...)
// 返回值大于0,写入的个数;否则失败
int fprintf(FILE *fp, const char *format, ...)
// int 返回读入的字符,失败返回 EOF
int getc(FILE *fp);
// 将字符写入文件,返回写入成功的个数,失败返回 EOF
int putc(int character, FILE *fp);
char * fgets(char *str, int num, FILE *fp);
char * fputs(char *str, FILE *fp);
// 移动文件指针,到指定的位置读或写
int fseek(FILE *stream, long offset, int whench)
// 返回当前文件指针,相对于文件开头的位移量
long filesize = ftell(fp);- 打开模式
w只写,创建文件或覆盖已经存在的文件r只读,打开存在的文件,若文件不存在,报错aappend 追加文件,若文件不存在,报错rb、wb、ab二进制模式r+、w+、a、等
FILE *fp;
fp = open("./a.txt", "a")
if (fp==0)
{
printf("open file err");
return 1;
}
fclose(fp);常见错误
- 变量未定义:
warning: 'xxx' is used uninitialized in this function [-Wuninitialized] - 定义变量未使用:
warning: unused variable 'xxx' [-Wunused-variable] return前一行缺少;:error: expected ',' or ';' before 'return'
扩展
GCC(GNU C Compiler)又称GNU C语言编译器,是由 GNU 开发的编程语言译器,最早只能处理C语言,后扩展为可处理C++、Fortran、Pascal、Objective -C、Java、Ada、Go以及各类处理器架构上的汇编语言等。因此,又称 GNU 编译器套件(GNU Compiler Collection)。- GCC 编译器是 Linux 系统下最常用的
C/C++编译器,大部分 Linux 默认安装