小恐的C语言学习笔记(完结)

273 阅读23分钟

hello world

#include <stdio.h>
int main()
{
  printf("hello world")
  return 0;
}
  • a#include <>引入头文件
    • astdio.h是一个标准库
    • d
  • s int main()是程序主函数
  • s return 0;是调用返回值给main来结束main函数
  • s printf()是包含在stdio.h头文件里的
    • a用作打印在屏幕上
    • d
  • s 大括号
    • a函数体
    • s代码题
    • s作用域
    • d
  • d

system函数

#include <stdio.h>
int main(void)
{
  system("calc")
}
  • aysytem可以打开一个外部的程序
  • d

占位符

  • aa
  • %d整型
  • %f单精度浮点型
  • %lf双精度浮点型
  • %o八进制输出
  • %x十六进制的int类型
  • %u输出一个十进制的无符号
  • %hu短整型
  • x无符号16进制整形
  • %e科学计数法
  • %c字符型
  • ss %s char*指针
    • aa
    • 输出字符串中的字符直至字符串中的空字符
    • (字符串以\0结尾即是空字符)
    • dd
  • %p以十六进制输出指针
  • %%一个百分号
  • s用法
    • aa
    • 代码:
    int a = 6;
    float b =2.333333printf("a的值是:%d",a);
    printf("b的两位是:%.2f",b);
    
    • 浮点类型如果只想显示后两位可以在占位符哪里写一个.2
    • dd
  • dd

数据类型

常亮与变量

C语言的32个关键字

char字符型
short int long整型
float单精度 double双精度浮点型
unsigned无符号,signed有符号有无符号
struct定义结构体,union定义联合体共用体,enum定义枚举复合型
void空类型
if,else`` switch, case, default,break条件判断语句
for, do, while break, continue goto return循环语句
auto,extern,register,static,const存储类关键字
sizeof,typedef,volatile其它关键字

常量

  • aa

s不能发生改变的量

  • s关键字
    • aa
    • const
    • dd
  • s常量名的定义
    • aa
    • const 数据类型 常量名 = 值 ;
    const int a =100 ;
    
    • dd
  • dd

标识符

  • aa
  • 标识符不能使用关键字
  • 标识符不能数字开头
  • 标识符可以使用下划线做开头( _ )
  • 标识符区分大小写
  • dd

类型限定

  • aa
  • s限定符
    • aa
    • ss extern
      • aa声明一个变量
      • extern声明的变量没有建立存储空间
      • 普通的int就是extern
      • ss定义变量
        • aa
        • extern int a =10;
        • dd
      • dd
    • ss const
      • aa
      • 定义一个常量
      • 常量不能被修改
      • dd
    • ss Volatile
      • aa
      • 防止编译器优化代码
      • dd
    • ss register
      • aa
      • 定义寄存器变量
      • 提高效率
      • 建议型指令非命令型指令
      • ss 如果cpu有空闲寄存器
        • aa
        • 就会生效
        • 如果没有就会无效
        • dd
      • dd
    • dd
  • dd

字符串格式化输出和输入

字符串常量

  • aa
  • 字符串是内存中一段连续的char空间,以'\0’(数字0)结尾。
  • 字符串常量是由双引号括起来的字符序列,如“china”、 “cprogram”,“$12.5”等都是合法的字符串常量。
  • ss如果定义字符和字符串
    • aa
    • 字符常量是一个字符空间
    • ss字符串常量一个字符占两个字符空间
      • aa
      • 因为字符串常量会自动包含一个\0
      • dd
    • ss字符串数组
      • aa
      • char a[] = "hello world" ;
      • dd
    • dd
  • dd

printf函数与putchar函数

  • aa printf是输出一个字符串
  • ss putchar输出一个char
char ch ='a';
putchar(ch);
  • aa
  • 可以是打印数字0到127对应的数字编码
  • 可以打印转义字符
  • 可以说一个字符
  • dd
  • dd

scanf函数与getchar函数

  • aa
  • scanf通过%转义的方式可以得到用户通过标准输入设备输入的数据
  • getchar是从标准输入设备读取一个char
  • dd

运算符表达式

常用运算符分类

  • aa
  • 运算符类型
  • s算术运算符
    • 用于处理四则运算
    • d
  • s赋值运算符
    • 用于将表达式的值赋给变量
    • d
  • s比较运算符
    • 用于表达式的比较,并返回一个真值或假值
    • d
  • s逻辑运算符
    • 用于根据表达式的值返回真值或假值
    • d
  • s位运算符
    • 用于处理数据的位运算
    • d
  • s sizeof运算符
    • 用于求字节数长度d
  • dd

算数运算符

  • aa
  • +加
  • -减
  • *乘
  • /除
  • %取余
  • ++前或后自加1
  • --前或后自减1
  • dd

指针入门篇

  • aa
  • 创建了一个变量
    • aa
    • 变量在内存某个地址当中存放了数值
    • dd
  • 要想获取该变量的地址就要使用指针了
#include <stdio.h>
int main(void)
{
  int num =10 ;
  printf("num的值=%d num的地址=%p"num,&num)
}
  • %p是输出指针
  • &是取出num的地址
  • ss指针定义
int i = 123 ;
int *zhiVzheE = i; 
  • aa
  • *代表指针
  • zhiVzhenE指向了变量i
  • dd
  • 指针本身也有自己的地址
  • ss使用指针来输出指向的那个变量地址的数值
  • ss使用指针来输出指向的那个变量地址的数值代码:
int a = 6;
int zhiVzhenE = a;
printf("指针指向的值是%d",*zhiVzhenE) ;
  • ss使用指针来输出指向的那个变量地址的数值
    • aa
    • *号能找到指向的变量地址并且输出
    • dd
  • ss基本的数据类型都有对应的数据类型
    • aa
    • 数据类型 *指针名
    • dd
  • ss指针不止一种
    • aa还包括
    • 指向数组的指针
    • 指向结构体的指针
    • 指向共用体ed指针
    • dd
  • dd

值传递与地址传递

  • aa
  • ss c语言传递参数(或者叫赋值)可以有两种形式
    • aa
    • 值传递
    • ss传递指针
      • aa
      • 传递指针也叫地址传递
      • dd
    • dd
  • ss默认传递值的类型
    • aa基本数据类型
    • 整型类型
    • 小数类型
    • 字符型
    • 结构体
    • 共用体
    • ss值传递代码
    int bianMliangM1 =10;
    int bianMliangM2 =bianMliangM1;
    
    • ss值传递
      • aa
      • bianMliangM1赋值给了bianMliangM2这就叫值传递
      • bianMliangM1通过地址指向了bianMliangM2的地址空间
      • 把bianMliangM1的值复制一份给bianMliangM2的空间
      • 两个变量其中一个改变了也不会改变另一个变量
      • dd
    • dd
  • ss默认传递地址
    • aa
    • ss指针
      • aa如果是指针
      • 将存储指针的地址传递给接受的变量
      • ss理解代码
      • 代码段:
      int num =100;
      int *p = num;
      
      • 代码段x
      • ss理解
        • aa
        • 把num的地址赋值给了指针*P
        • *p也有一个自己的指针地址
        • *p也有一个指向num的地址
        • 并没有把num的数值传递给*p指针
        • 如果*p=20那么num里的值也会跟着改变
        • dd
      • dd
    • ss数组
      • aa如果是数组
      • 就将数组的首地址传递给接收的变量
      • dd
    • dd
  • dd

常量

  • aa常量是固定的值
  • 在程序执行期间不能改变
  • 常量可以是任意的类型
  • 定义之后就不能再被修改
  • dd

define预处理器

#include<stdio.h>
#define PI 3.14
int main()
{
  double area;
  double r = 1.2;
  area = PI*r*r;
  printf("面积:%.2f"area);
  getchar

  return 0;
}
  • aa define定义
    • aa
    • #define 常量名 常量值
    • dd
  • 不需要加类型
  • define定义之后是不能被修改的
  • define可以配合ifend、ifndef、endif来使用
//如果有这句话就会就算是打开了反过来就是没有打开
#include<stdio.h>
#define tiaoWshiM
 int main()
 {
  #ifdef tiaoWshiM;
  printf("打开了")
  #endif
  #ifdef tiaoWshiM
  printf("没有打开")
  #endif
  return 0;
 }
  • dd

const关键字

  • aa const的定义
    • aa可以声明指定类型的常量
    • const 数据类型 常量名 =常量值;
    • dd
  • dd

运算符

  • aa
  • ss算数运算符
    • aa
    • +
    • -
    • *
    • /
    • %取模
    • ++自增
    • --自减
    • dd
  • ss赋值运算符
    • aa
    • =等于
    • +=加等于
    • -=减等于
    • dd
  • ss关系运算符(比较运算符)
    • aa
    • >大于
    • >=大于等于
    • <小于
    • <=小于等于
    • ==等于
    • dd
  • ss逻辑运算符
    • aa
    • &&逻辑与
    • ||逻辑或
    • !逻辑非
    • dd
  • ss位运算符
    • aa
    • &按位与
    • |按位或
    • ^按位异或
    • ~按位取反
    • dd
  • ss三元运算符
    • aa
    • 表达式?表达1:表达2
    • dd
  • dd

流程控制

  • aa流程控制分为三种
  • 顺序控制
  • 分支控制
  • 循环控制
  • dd

顺序控制

  • aa
  • 程序从上到下逐行的进行
  • 没有任何的判断和跳转
  • dd

分支控制

if-else

  • aa有三种

单分支

  • aa
/*
if(条件表达式)
{
 执行代码块;
}
*/
#include<stdio.h>
int main()
{
 int age =0;
 printf("请输入年龄")
 scanf(%d,&age);
 if(age>=18)
 {
   printf("你已经是个大孩子了");
 }
 if(age<18)
 {
   printf("你还未成年");
 }
 return 0;
}
  • 如果括号里的表达式是真就就执行代码块
  • 反之不执行
  • dd

双分支

  • aa
  • 语法
if(条件表达式)
{
  执行的代码快1
}else{
  执行的代码块2
}
  • 真就执行代码块1
  • 假就执行代码块2
  • dd

多分支

  • aa语法
if(条件表达式1)
{
 执行代码块1; 
}
else if(条件表达式2)
{
  执行代码块2;
}
esle{
  
}


  • dd

switch关键字

  • aa语法
#include<stdio.h>
int mian()
{
  int a = 0 ;
  scanf("%d",&a);
  switch(a)
  case 1:
  printf("星期一");
  break ;
  case 2:
  printf("星期二");
  break ;
  case 3:
  printf("星期三")
  break ;
   case 4:
  printf("星期四")
  break ;
  case 5:
  printf("星期无")
  break ;
   case 6:
  printf("星期六")
  break ;
    case 7:
  printf("星期天")
  break ;
  default:
  printf("匹配错误")
  break ;
}
  • break表示终止
  • switch如果没有break就会执行所有的常量语句块
  • default如果匹配都不成功就执行这里的语句
  • ss switch是个常量表达式
    • aa
    • cha
    • short
    • int
    • long
    • 枚举
    • dd
  • case右边不能是变量而是常量
  • dd

循环控制

for循环控制

/*
for(循环变量初始化;循环条件;循环变量迭代)
{
  循环操作
}
*/
#include<stdio.h>
 
 int main()
 {
  for(int i=1; i<5; i++)
  {
    prtinf("循环了%d次\n",i);
  }
  return 0;
 }
  • aa
  • ss for循环体执行流程
    • aa
    • 从循环变量初始化
    • 然后判断循环条件看是否条件成立
    • 如果条件成立就进入循环体
    • 然后进入循环变量的迭代(++或--)
    • dd
  • 循环初始化语句可以是多条用逗号隔开
  • for循环变量的迭代语句也可以是多条用逗号隔开
  • dd

while循环控制

/*
①循环变量初始化;
②while(循环条件)
{
 ③循环体语句(多条语句);
  ④循环变量的迭代;
}
*/
#include<stdio.h>
int mian()
{
  int a= 1;
  while(a<=5)
  {
    printf("数字%d",a);
  }
  return 0;
}

do while循环控制语句

/*
①循环变量的初始化
do{
    ②循环体(多语句);
    ③循环变量迭代;
}while(④循环条件);
*/
#include<stdio.h>
int mian()
{
  int a = 1 ;
  int max = 5//循环的最大值
  do{
    printf("数字%d",a);
    a++;
  }(i<=max);
  return 0;
}
  • aa
  • 先初始化变量
  • 先执行一遍循环体
  • 再进入判断语句
  • 注意while();记得加分号
  • dd

循环嵌套

  • aa
  • 循环之间是可以额无限嵌套的
  • 嵌套最少不要超过二
  • 嵌套最多不要超过三
  • dd

跳转控制语句

break

/*
if(条件)
{
  break ;
}
*/
  • aa
  • 再执行循环的过程中,当某个条件满足时可以提前终止该语句
  • dd

continue

/*
if(条件)
{
  continue ;
}
*/
for(int i;i<10;i++)
{
  if(i==3&&i==6&&i=9;i++)
  {
    continue ;
  }
}
  • aa
  • 不跳出循环体只是跳过本次的循环,继续执行当前的循环
  • 循环只要遇到369就会跳过369输出124578和10
  • dd

goto

  • aa
  • 无条件的跳转到程序指定的行
  • goto通常配合着条件语句来使用
  • 一般在C语言编程的时候不主张使用goto,可能会照成程序的逻辑流程混乱
  • ss goto关键字
    • aa
    • ss goto
      • aa
      • goto tiaoMzhuanV
      • 定义了一个goto叫tiaoMzhuanV
      • dd
    • ss statement
      • aa
      • tiaoMzhuanV:statement
      • 当出现的时候就会直接跳转到这个语句的地方
      • dd
    • dd
  • dd

枚举

#include<stdio.h>
int main()
{
  enum yiEzhouE
  {
    xingEqiEyiE=1,
    xingEqiEerM=2,
    xingEqiEsanE=3,
    xingEqiEsiM=4,
    xingEqiEwuV=5,
    xingEqiEliuM=6,
    xingEqiEtianE=7
  };
  enum yiEzhou zouEwuV = xingEqiEwuV ;
  return 0;
}
  • aa
  • ss语法
    • aa
    • enum 枚举名{枚举元素1……枚举元素N}
    • dd
  • 记得枚举后面加分号(:)
  • ss枚举类型赋值只能是包含在里面的
    • aa
    • 比如枚举yiEzhouE枚举变量新建只能使用枚举内的值比如xingEqiEyiE也就是星期一
    • dd
  • 如果有的没有赋值那么就会自动接上上一个有过赋值的枚举元素下一个就是上一个的+1
  • 枚举元素要用逗号(,)隔开
  • 如果第一个枚举元素没有赋值那么第一个枚举的值是0,后面的以此类累加
  • dd

函数

  • aa
  • 为了某一功能的独立的功能
  • ss函数分为两种
    • aa
    • 自定义函数
    • 系统函数
    • dd
  • 有的地方会把函数说成方法
  • 函数基本语法
/*
返回类型 函数名(形参列表)
{
  执行语句
  return 返回值;
}
*/
#include<stdio.h>
int xiangEjiaE(int a,int b)
{
  int jieWguoV
  jieWguoV = a + b;
  return jieWguoV
}
int main()
{
  int c=1;
  int d=1;
  int xiangEjiaEjieWguoV
  xiangEjiaEjieWguoV = xiangEjiaE(a,b);
  printf("输出结果%d",xiangEjiaEjieWguoV);
}
  • 没有返回值的void的类不返回任何东西也不用return
  • 函数中的变量名要和形参列表中的变量名称一样
  • dd

函数的调用机制

  • aa
  • 当执行一个函数的时候就会开辟一个独立的空间
  • 每个栈都是相互独立的
  • ss函数执行完后,会返回到调用的函数位置,继续执行
  • dd

函数的使用注意事项和细节

  • aa
  • 传递参数的时候可以是值传递也可以是传递指针
  • 函数里的变量是局部的,函数外不能使用
  • ss基本数据类型默认是值传递,即进行值拷贝
    • aa
    • 在函数内修改不会影响到原来的值
    • dd
  • ss希望函数内的变量能影响外面的变量,可以传入变量的地址&
    • aa
    • 函数以指针的方式操作变量
    • 从效果上看类似引用(即传递指针)
    #invlude<stdio,h>
    void zhiVzhenEchuanWdiM(int *p)
    {
      //*是取值符
      //是得到指针指向的变量
      *p++
    }
    int main()
    {
      int a=4;
      //&是解引用把a传到指针*p里面去
      zhiVzhenEchuannWdiM(&a);
      
    }
    
    • 可以通过&解引用传递地址
    • 可以通过*来指向变量
    • dd
  • ss c语言不支持函数重载
    • aa
    • 即不能通过参数的个数不同
    • 或则类型不同来区分函数
    • dd
  • dd

头文件

  • aa
  • 在实际的开发中,往往需要再不同的文件中去调用其它文件的定义的函数
  • 头文件的扩展名是.h
    • aa
    • 包含了C函数声明和宏定义,被多个源文件中引用共享
    • ss有两种类型的头文件
      • aa
      • 程序员编写头文件
      • 标准库自带的头文件
      • dd
    • dd
  • ss在程序中使用头文件
    • aa
    • 需要使用c预处理指令:#include来引用它
    • dd
  • #include叫做文件包含指令用来引入对应的头文件
  • ss #include的处理很简单
    • aa
      • aa
      • 将头文件的内容插入到该命令所在的位置
      • 从而把头文件和当前源文件文件连接成一个源文件
      • dd
    • ss建议把所有的常量、宏、系统全局变量和函数原型都写在头文件当中
      • aa
      • 需要的时候随时引用这些头文件
      • dd
    • dd
  • ss定义头文件
    • aa
    /*touWwenWjianM.h头文件*/
    声明同名源文件里的常量、宏、系统全局变量、函数方法
    
    常量、宏、系统全局变量、函数方法
    /*touWwenWjianM*/
    
    • ss需要两个同名但不同后缀的文件存在
      • aa
      • .h的头文件
      • .c的源文件
      • dd
    • 把源文件里的常量、宏、系统全局变量、函数声明在.h的同名的头文件里就行了
    • ss在头文件里做函数声明
      • aa
      • int xiangEjiaE(int a,int b);即可
      • 不要忘记在结尾加分号(英文的;)
      • dd
    • dd
  • 要想在其它原文件里使用这个头文件一定要用#include""来引用
  • 引用自己写的不能使用将括号(<>)而是使用双引号("")
  • 引入头文件就相当于把头文件的同名源文件里的代码复制到引用的那个源文件里面
  • #include<>引入的是标准库的文件双引号引入的是非标准库里的文件
  • 头文件里也能套娃引入其它的头文件
  • dd

变量的作用域

  • aa
  • 函数内部声明/定义的的局部变量,作用域仅限在函数内部
  • 函数内的局部变量如果与全局变量同名,它们会优先使用局部变量(编译器使用就近原则)
  • 作用域就是大括号{}内的内容
  • ss在函数体以外的地方定义的变量称之为全局变量在哪里都能使用
    • aa
    • 通常把全局变量创建在一个.h头文件里
    • dd
  • dd

变量初始化

  • aa
  • 局部变量系统不会对其初始化需要手动初始化
  • 局部变量不初始化会导致地址存在垃圾数据
  • dd

static关键字

static局部变量

  • aa
  • static是静态的变量修饰关键字
  • static可以用在局部变量
  • static局部变量声明未初始化编译器会默认为0
  • ss静态局部变量存储于进程的静态存储区(全局性的空间)
    • aa
    • 只会被初始化一次
    • 即使函数返回它的值也会保持不变
    • 不会自己释放掉
    • dd
  • 存放在栈区的变量执行完会自我释放静态存储区不属于栈区
  • dd

全局static变量

  • aa
  • ss:普通的全局变量对整个工程可见
    • aa
    • 其它文件可以使用extern外部声明后直接使用
    extern int jingMtaiMbianMliangM;//这个静态全局变量在其它源文件里
    
    • ss也就是说其它文件不能定义与其相同名字的变量
      • aa
      • 静态全局变量只能对当前文件可见
      • 其它文件不可访问
      • 其它文件可以定义与其相同名的变量两者互不影响
      • dd
    • dd
  • dd

static静态函数

  • aa
  • 在很熟返回类型前加static就是静态函数
  • 非静态函数可以在另一个文件中通过extern引用
  • 静态函数只能在声明它的文件中可见其它文件不能被引用该函数
  • 不同的文件可以使用相同名字的静态函数互不影响
  • dd

基本数据类型与字符串类型的转换

  • aa
  • 在程序开发中需要将基本数据类型转换成字符串类型(即cahr数组)
  • dd

sprintf函数

  • aa
char zfc[20];
int a=123456
sprintf(zfc,"%d",a);
  • 作用就是把字符打印到字符数组中去
  • C语言没有字符串类型
  • dd

字符串转换为基本数据类型

  • aa
  • ss引入头文件
    • aa
    • stdilib.h
    • dd
  • 代码
char zfc[20];
//将zfc转换为整数
int a = atoi(zfc);//atoi是stdilib.h头文件里的
  • 将cahr类型转换为整型只能是数字不能是字母
  • dd

预处理命令和宏定义

  • aa
  • 比如说在使用库函数之前引入了#include头文件
  • 以#号开头都称之为预处理命令
  • 在编译之前对源文件进行简单的加工过程就是预处理
  • 预处理命令要放在所有函数之前
  • 一般都放在源文件前面
  • ss系统自动调用预处理程序对源程序中的预处理部分作处理
    • aa
    • 处理完毕之后进入对源程序的编译
    • dd
  • dd

宏定义

  • aa
  • ss语法
    • aa
    • #define 宏名 字符串
    • 字符串可以是数字,表达式,if语句,函数
    • 预处理程序对他不做任何的检查
    • dd
  • 是预处理命令之一
  • ss用标识符来表示一个字符串
    • aa
    • 如果在后面出现标识符
    • 就全部替换成指定的字符串
    • dd;
  • ss取消宏定义
    • aa
    • #undef 宏名
    • dd
  • 宏都建议用大写字母来定义
  • dd

带参数的宏定义

  • aa
  • 在宏定义中参数称为形式参数
  • ss带参数的宏
    • aa
    • 在展开的过程中
    • 不仅要进行字符串替换
    • 还要用实参去替换形参
    • dd
  • ss语法
    • aa
    • #define 红名()
    #define MAX(a,b)(a>b)?a:b
    int mian()
    {
      int x,y,max;
      scanf("%d %d",&x,&y);
      max=MAX(x,y);
      printf("max=^d\n",max);
      return 0;
    }
    
    • dd
  • dd

带参宏和函数的区别

  • aa
  • 宏是字符串的替换不会对表达式进行运算
  • ss宏在编译之前就已经处理好了
    • aa
    • 没有机会参与编译
    • 不会占用内存
    • dd;
  • ss函数是一段可以重复的代码::
    • aa
    • 会被编译
    • 会给他分配内存
    • 每次调用函数都是执行这块代码
    • dd
  • dd;

常见的预处理指令

  • aa
  • #空空指令,没有任何效果
  • #include包含一个源代码文件
  • #define定义宏
  • #undef取消定义宏
  • #if如果给定条件为真,则编译下面代码
  • ifndef如果宏没有定义,则编译下面代码
  • #elif如果当前#if给定条件不为真,当前条件为真,则编译下面代码
  • #endif结束一个#else条件编译快
  • dd

数组

  • aa
  • ss数组可以多个同一类型的
    • aa数组也是一种数据类型
    • 是结构类型
    • dd;
  • 一旦被定义了长短就固定下来了
  • 传递是以引用的方式传递(传递的是地址)
  • 构造类型里没有指针
  • ss数组定义
数据类型 数组名[数组的大小]; 
  • aa
  • 中括号是下表从0开始
    int shuMzuV1[6];
    shuMzuV1[0]=1;
    shuMzuV1[1]=2;
    shuMzuV1[2]=3;
    shuMzuV1[3]=4;
    shuMzuV1[4]=5;
    shuMzuV1[5]=6;
    
  • 数组只能存入相同类型的变量不能存入其它类型的变量
  • 数组的首地址是0
  • dd
  • dd;

数组的初始化

-。第一种初始方法

int shuMzuV[3]
shuMzuV[0]=1;
shuMzuV[1]=2;
shuMzuV[2]=3;
```c
-。第二种初始方法   

int shuVzu2[3]={1,2,3};

-。第三种 
```c
int shuMzuV3[]={1,2,3,1,21,21,1,2};

字符数组

。用来存放字符的数组

char a[10];//长度为10
char b[5][10]//二维字符数组
char c[20]={'a','b','c','d','e','f','g'};//给数组元素赋值

。 在C语言中没有字符串类型

字符串的注意事项

。C语言中字符串实际上是使用了null字符('\0')终止一堆字符数组
。如果字符串大小没用完就会在有字符的下一个字符变量给如'\0'
'\0'表示null空字符 。字符数组的最后一位必须是\0如果最后一位使用了其他的字符会有出错的风险

char a[3]{'a','b','c'};//最后一位是c没有地方放置\0
char b[4]{'a','b','c',''};//后面会自动追加\0

。不写字符长短的字符数字会自动追加\0

字符数字指针

char *zhieVzhenEshuMzu[]="hello";

。字符数组由若干个元素组成
。。每一个元素放一个字符
。字符指针变量存放的是地址 。。数组内存放的变量地址是紧挨着的比如0x1110,那么下一个就是0x1111,下一个就是0x111a
。修改字符数组值的时候一定要使用用下标来修改不能直接修改

char a[10];
a ="hello"//这是错误的
a[0]='h';//正确
a[1]='e';//正确

。字符指针数组可以直接修改值

char *a[]="abcdefg";
a="hello";

。。原来的地址回收了地址也就改变了

二维数组

。数组就像是鸡蛋托的行和列
。定义

int a[4][5];

。初始化

int a[4][6]={
{1,2,3,4,5,6},
{1,2,4,3,5,2},
{1,5,9,5,6,7},
{1,3,5,4,6,7}
};

。二维数组的地址是连续的

指针的运算

。指针是一个用数值表示的地址能对指针执行运算

#include<stdio.h>
const int MAX = 3 ;
int mian
{
  int var[]={10,20,300};//int 数组
  int ,*ptr;//ptr是指针

  ptr=var; //ptr指向了var的首地址
  for(int i=0;i<MAX;i++)
  {
    printf("var[%d]地址=%p",i,ptr);
    prtinf("存储值:var[%d]=%d\n",i,*ptr);//星号可以把变量值给打印出来
    printf(ptr++;)//ptr=ptr+1(一个int的字节数)存放值加4个字节(int)
  }
  return 0;
}

。指针的加减就是指针的地址的位置加与减比如0x11112如果+6那么就等于11118

指针比较

。 数组和数组之间的比较 。符号 == < <= > >=

int var[]={10,20,30};
int *zhiVzhenE
zhiVzhenE =var;
if(zhiVzhenE==&var[1])
{

}
if(zhiVzhenE==var)
{

}

指针数组

。要让数组的元素指向int或其它数据类型的指针可以使用指针数组 。指针数字的声明

int a[5]={1,2,3,4,5};
int  *zhiVzhenE[5];
zhiVzhenE=a;//[0]
zhiVzhenE[1]=&a[1];
zhiVzhenE[2]=&a[2];
zhiVzhenE[3]=&a[3];
zhiVzhenE[4]=&a[4];

指向指针的指针(多重指针)

。一种多级间接寻址的形式或则说是一个个指针链
。当定义了一个指向指针的指针时,第一个指针就包含了第二个,第二个就包含了第三个指针

#include<stdio.h>

int mian()
{
  int var;
  int *yiEjiWzhiVzhenE;
  int **erMjiWzhiVzhenE;
  var=10000;
  yiEjiWzhenVzhenE= &var;
  erMjiWzhiVzhenE= &yiEjiWzhiVzhenE;

  return 0;
}

传递指针(地址)给函数

。当函数的形参是指针类型的时候,是使用该函数时需要传递指针或者地址又或者数组

#include<stdio.h>
void hanWshuMzhiVzhenE(int *p);//这只是个声明真正的在下面
void main()
{
  int i,num=90;
  int *p = &num;
  hanWshuMzhiVzhenE(&num)
}
void hanWshuMzhiVzhenE(int *p)
{
  *p += 1;
}

。传递指针会把原来的值给改变

返回指针函数

。用指针作为函数返回值注意,函数结束后会销毁在内部的所有定义的数据函数返回不能指向这些数据

#include<stdio.h>
int *func()
{
  int n = 100;
  return &n;
}
int mian()
{
  int *p = func();
  int n;
  n=*p;//这里的数据在这时候已经销毁,数据还在只不过是程序放弃了它的权限其它代码继续使用这块内存
  getcahr();
  return 0;
}

。。调用完就会立即释放aa{
如果当前没有其它变量使用这块区域那么这块的内存地址的原来的值就还会存在
}dd
。C语言不支持在调用函数时返回局部变量的地址
。。如果有这样的需求,需要将局部变量加一个修饰符static关键字aa{
存放在静态数据区
存放在该区的变量就不会再被其它的变量占用
}dd

函数指针

。一个函数总是占用一段连续的区域
。。函数名在表达式中有时也会被转换为该函数aa{
所在内存区的首地址,这和数组名非常类似
}dd
。把函数的首地址(后者入口地址赋予一个变量
。。使指针变量指向aa{
函数所在的内存区域
然后通过指针变量就可以找到调用该函数
这就是函数指针
}dd
。函数指针定义

int x,y,maxVal;
//hanWshuzhiVzhenE是函数指针的名字
//int是该函数指针指向的函数是返回int类型
//(int,int)表示该函数指针指向的函数形参是接受两个int
//(int,int)里也可以写成(int a,int b)
int (*hanWshuMzhiVzhenE)(int,int)=max;
printf("lnput two numbers:");
scanf(%d%d",&x,&y);
maxVal = (*hanWshuMzhiVzhenE)(int,int);
printf("hanWshuMzhiVzhenE:",hanWshuMzhiVzhenE);

回调函数

。函数指针变量可以作为某个函数的参数来使用,调回函数就是一个通过函数指针调用的函数 。简单讲就是回调函数是由别人的函数执行时调用你传入的函数

#include<stdio.h>
#include<stdlib.h>
//回调函数
void iniArray(int *array,int arraySize,int(*f)(void))
{
  for(int i=0;i<arraySize;i++)
  {
    //可以(*f)()也可以↓
    array[i] =f();//通过函数指针调用了getNextRandomValue
  }
}
//获取随机值
int getNextRandomValue(void)
{
  return rand();//通过函数指针调用了getNextRandomValue函数
}
int mian(void)
{
  int mayarray[10];//定义一个数字和int
  iniArray(mayarray,10,getNextRandomValue);
  for(int i=0;i<10;i++)
  {
    printf("%d",marray[i])
  }
}

空指针的使用

。指针变量存放的是地址,从这个角度看指针的本质就是地址
。变量声明的时候,如果没有确切的地址赋值,为指针付一个null值是好的习惯
。null是空指针

动态内存分配

。全局变量在内存的静态存储区
。非静态的局部变量存放在内存动态存储区的stack栈中
。临时使用的数据建立动态内存分配区域,需要随时开辟,不需要即使释放heap堆
。根据需要向系统申请所需大小的空间
。。由于未在声明部分定义其为变量或者数组aa{
不能通过变量名或者数组名来引用这些数据只能通过指针来引用
}dd

内存动态分配的相关函数

。头文件#include<stdlib.h>声明了四个关于内存动态分配的函数
void *malloc(uslgned size)
。。aa{作用――在内存的动态存储区(堆区)中分配一个长度为size的连续空间。
形参size的类型为无符号整型,函数返回值是所分配区域的第一个字节的地址,即此函数是一个指针型函数,返回的指针指向该分配域的开头位置。
malloc(100);开辟100字节的临时空间,返回值为其第一个字节的地址
}dd
void *calloc(unsigned n,unsigned size)
。。aa{作用――在内存的动态存储区中分配n个长度为size的连续空间
这个空间一般比较大,足以保存一个数组
用calloc函数可以为一维数组开辟动态存储空间
n为数组元素个数,每个元素长度为size.
函数返回指向所分配域的起始位置的指针;分配不成功,返回NULL。
p = calloc(50,4);//开辟50*4个字节临时空间,把起始地址分配给指针变量p}dd
void free(void *p)
。。作用――释放变量p所指向的动态空间,使这部分空间能重新被其他变量使用。
。。p是最近一次调用calloc或malloc函数时的函数返回值
free函数无返回值
free(p);//释放p所指向的已分配的动态空间
void *realloc (void *p,unsigned int size)
。。作用――重新分配malloc或calloc函数获得的动态空间大小
将p指向的动态空间大小改变为size,p的值不变,分配失败返回NULL
。。realloc(p,5O);// 将p所指向的已分配的动态空间改为50字节
。c99标准把以上malloc,calloc,realloc函数的基类型定为void类型
。。这种指针称为无类型指针(typeless pointer),即不指向哪一种具体的类型数据
。。只表示用来指向一个抽象的类型的数据,即仅提供一个纯地址,而不能指向任何具体的对象。

void指针类型

int a=3;//定义a为整型变量 int * p1= &a;//p1指向int型变量
char * p2;// p2指向char型变量 void * p3;//p3为无类型指针变量(基类型为void型)
p3一(void * )pl;//将pl的值转换为void *类型,然后赋值给p3 p2=(char * ) p3;//将p3的值转换为char *类型,然后赋值给p2 printf(" %d", * p1);//合法﹐输出a的值
p3=&a; printf("%d", * p3)﹔//错误, p3是无指向的,不能指向a

结构体

。语法

struct renW//创建结构体
{
  int nianWlingW;//年龄
  char *mingWziM//名字
};
struct renW ziEliaoM1//结构体变量声明
struct renW ziEliaoM2;
ziEliaoM1.nianWlingW=16;
ziEliaoM1.mingWziM="张三";
ziEliaoM2.nianWlingW=15;
ziEliaoM2.mingWziM="李四"
printf("姓名:%s,年龄:%d"ziEliaoM1.mingWziM,ziEliaoM1.nianWling);
printf("姓名:%s,年龄:%d"ziEliaoM2.mingWziM,ziEliaoM2.nianWling);

。结构体最后是由分号的

结构体与结构体变量

。结构体是自定义得到类型 。。表示的就是一种数据类型 。结构体变量代表一个具体变量 。就像一个模板 。。定义出来的结构体变量都含有相同的成员,也可以将结构体比较“图纸” 。。将结构体变量比作为“零件” 。。根据同一张图纸生产出来的零件的特性都是一样的

结构体成员

。结构体首字母最好大写

struct 结构体名称
{
  成员列表;
};

。有的书上写的成员”结构体包含的变量“ 。成员是结构体的一个组成部分,一般是基本数据类型 。。也可以是数组、指针、结构体等 。机构提变量创建完最好必须赋值否则会导致异常

结构体的匿名结构体

。定义

struct {
char *mingWziM;//名字
int nianWlingW;//年龄
double shenEgaoE;//身高
double tiVzhongM;//体重
}diMyiE,diMerM;

。只有这两个结构体变量不能再增加了

共用体

。属于构造体类型 。可以包含多个不同类型的成员 。共用体由很多个叫法 。。联合体 。共用体的定义

union 共用体名
{
  成员列表
};

。。记得结束的时候由分号 。共用体的所有的成员占用同一段内存 。。修改一个值会影响其余所有成员

union gyt
{
  int n;
  char ch;
  double f;
}
union gyt a,b,c;

。共用体是以最大的那个变量类型为最大的字节为准