C 语言介绍

发布时间: 更新时间: 总字数:2713 阅读时间:6m 作者: IP上海 分享 网址

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 双精度浮点实数型
    • short
    • long
    • unsigned int
    • unsigned 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

操作符

  • 算术运算符:+-*/%++--
  • 比较运算符:><>=<=!=
    • 比较结果:10
  • 逻辑运算符:与 &&、或 ||、非 !
    • 比较结果:10
  • 符合运算符:-=+=*=%=&=|=^=~=
    • 比较结果:10

函数

  • 函数:一个命名的程序块,用来执行专门的任务
  • 定义
/* 函数定义 */
返回值类型 函数名(形参类型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 响铃
      • \' 单引号
      • %% 百分号 %
    • 占位符
      • %c char 类型
      • %d int 类型
      • %f float 类型
      • %lf double 类型
      • %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 只读,打开存在的文件,若文件不存在,报错
    • a append 追加文件,若文件不存在,报错
    • rbwbab 二进制模式
    • 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 默认安装
Home Archives Categories Tags Statistics