《C语言程序设计教程》(一)

来源:互联网 发布:初学者模拟炒股软件 编辑:程序博客网 时间:2024/06/06 01:17

      • 标识符规则
      • 常量变量
        • 变量的初始化
      • 数据类型
        • 实型数据
        • 字符型数据
      • 基本表达式和运算符
        • sizeof
        • 类型强制转化
        • printf格式控制字符
        • 附加格式符
        • putchar
        • 标准输入
        • scanf调用注意点
        • getchar
        • 条件运算条件表达式
        • if条件
        • for
        • breakcontinue
        • 判断是否是素数
        • 数组
        • scanf函数
        • getchar方法
        • 字符数组
        • 字符串
        • 字符串的输入输出
        • 字符串处理函数
        • 指针
          • 访问类型
          • 指针变量定义
          • 指针的比较
        • 指针和一维数组关系
          • 利用指针遍历一维数组的两种方法
        • 2维数组指针
          • 二维数组的指针变量
        • 字符串指针
        • 字符串指针变量使用的注意点
        • 函数返回值是指针
        • 指向函数的指针
        • 二级指针
        • 指针函数
        • 数组指针
        • 指针tip
        • 结构体
        • 结构体变量的成员引用操作
        • 结构体变量的初始化
        • 结构体与数组
        • 结构体如何访问数组成员
        • 结构体与指针
        • 结构体链表
          • 动态内存分配
          • 内存释放
        • 共用体
          • 共用体的定义
          • 共用体的访问对象
          • 结构体和共用体的联合使用
        • 枚举
        • typedef
        • 函数的申明与调用
        • 参数传递
        • 局部变量全局变量
        • 变量的存储类别

标识符规则

  1. 标识符只能由字母、数字、下划线组成。
  2. 标识符的有效长度是1-255。
  3. 标识符的第一个字符必须是字母或者数字。
  4. 标识符在大小写是区分。
  5. 标识符不能与c的关键字相同。

常量、变量

int c= 7;#define PAI = 3.1415926;//常量的标识符全好是大写。

变量的初始化

可以多个同类型的一起赋值

int c= 7,b = 6;

数据类型

实型数据

也称为浮点数。两种表现形式:

  • 十进制小数
  • 指数形式
  double c = 1.6e3;//这里用大小的e无所谓  一般形式:aEn  a为十进制数,n为阶码,表示指数,必须是十进制整数,正负都可以。

需用的注意以下几点:

  1. 阶码之前必须有十进制的数。
  2. 指数不能为小数。

在实型计算中,不区分单精度还是双精度,都按照double,除非,你在数字后面指定了f或F,则认为是float。

double 提供16位有效数字,就是7位整数。
float提供7位有效数字,就是16位整数。

字符型数据

字符常量是用单引号括起来的字符。

  • 只有用单引号括起来的才是字符常量,用双引号或者其他符号括起来不是字符常量。
  • 字符常量只能是单个字符,不能是多个,转义的除外。
  • 字符常量以ASCLL码存储,范围0-255,字符常量是以ASCLL
  • 等价的整数值就行运算。

    转义字符

是一种特殊的字符常量,以\开头,有特定的含义。

\n 回车换行
\t 横跳下一个制表符
\b 退格
\r 回车
\f 走纸换页
\ 反斜线\
\’ 单引号
\” 双引号

字符变量

 char o = 'a';

一个字符变量占一个字节的分配空间。
一个中文汉字=两个字符,占2个字节。

字符串常量

字符串常量是由一对双括号括起来,系统会自动在每个字符串结束后面加一个字符串结束标志’\0’。

字符常量和字符串常量区别

  1. 字符串由单括号括起来,字符串常量是由双括号括起来的
  2. 字符串只能是单个字符(除转义外),字符串常量可以含0个或多个。

在c语言中,可以把一个字符常量赋值给字符变量,但是不能把一个字符串常量赋值给字符串变量,因为在
c中,没有定义相应的字符串变量,在后面会讲到用字符数组来存放一个字符串常量。

字符串常量的字节数,是字符串的字符个数+1,因为还有一个字符串结束标识符也占一个字节。

基本表达式和运算符

在c语言中一些基本的,我就不讲。

sizeof是用来结束数据的字节数。

/:是除法运算,如果参加运算的都是整型,那么结果就是整型,舍去小数;但是如果参加的运算有一个是实型,那么结果就是double。

%:求余运算,要求参加运算的量都是整型,然后取两数的余数。

sizeof

这个功能是求数据在内存中所占的字节数。

 int a = sizeof(10);  printf("%d",a);

类型强制转化

double  c = (double)(a+b);

printf格式控制字符

  1. %d 以十进制输出带符号整数,不包含正数符号。
  2. %o 以八进制输出无符号的整数,不输出前缀0。
  3. %x 以十六进制输出无符号整数,不输出OX。
  4. %u 以十进制输出无符号整数。
  5. %f 以小数形式输出单、双精度实数。
  6. %e 以指数形式输出单、双精度实数。
  7. %c 输出单个字符。
  8. %s 输出字符串。

附加格式符

  1. %-d %-c %-f 结果是左对齐,默认不加是右对齐。
  2. %+d 输出数字的时候带正负号。
  3. 空格 在输出正数时前面加空格,输出负数前面加负号。
  4. %ld %lf 用来输入长整型或者双精度数字。
  5. %md 代表整数输出几位数字。
  6. %m.nf 代表浮点数小数点后面n位。

putchar

可以用来输入字符常量和字符变量。

putchar('a');

标准输入

scanf(“格式控制字符”,地址表列);//地址列表中给出的各变量的地址,地址是通过取地址符&后面跟变量名来获取的。

scanf调用注意点

  1. 在输入数据的时候,两个数据一般用空格、enter、tab分开。
  2. 如果在各式控制字符中出现非格式控制字符,你需要在控制台也要原样输进去。
  3. 在输入数据的时候,不要指定精度。

getchar

这个函数执行的时候,会等待用户来输入一个字符。

条件运算、条件表达式

a>b?a:b

if条件

if的条件不一定是条件表达式为true,也可以是一个常量只要不是0,就可以的。

for

使用for循环的时候,如果3个判断条件没有时,也要要分号隔开。

 for(;(c = getchar())!='\n';)

break、continue

break:是跳出、结束循环,continue:是继续循环。break使用范围,就是在while、do….while、for、switch。而continue是结束本次循环 ,只能在while、do….while、for中使用,如果在while和do…while中使用,遇到continue会直接回到while后面的判断,而执行for的时候就直接到for循环的第三个条件表达式。

判断是否是素数

素数又称质数,是指不能被其他的整数整除的自然数,其算法思想:用n去依次除以2~~n-1之间的每一个数,如果每次整除,则n是素数;只要有一次实现整除,则判断不是质数,这个就是优化,没必要一直看到底。

 int n,i,flag;   i = 2;   flag = 0;   n = 0;   printf("请随便输入一个数:\n");   scanf("%d",&n);   for(i=2;i<=n-1;i++){    if(n%i==0){        flag =1;        break;    }   }   if(flag==1){   printf("这个数不是质数");   }else{    printf("这个是质数");   }

数组

c语言中的数组长度不可以用变量去定义。

scanf函数

利用scanf输入数据,一次数据输入的结束是通过,空格,Enter,Tab 来结束一次,特别是在循坏中。

getchar()方法

这个方法是用来输入字符的,并且返回这个字符的ascll编码,需要注意这个方法每次输入只能是一个字符,如果输入多个,则只接收第一个字符,另外,如果多个字符输入在一行,它的结束标志,就是回车,如果每输入一个字符换行,那么连续两次回车,就是结束标志。此外它比scanf输入字符好,因为空格它同样能处理,而scanf不行,它会当做结束符。

字符数组

char a[10]={'a''b''c''d'};如果字符数组的长度大于字符个数,那么系统默认会给其他数组元素为'\0'如果你在定义的时候,指定字符,那么可以不显示指定字符数组的长度,编译器会自动知道。

字符串

c语言的字符串是指有限个组成的字符序列,它是以字符数组的形式存放,并且以’\0’作为字符串的结束标志。

 char s[10] ={"hello"}

如果字符数组的长度大于字符个数,那么系统默认会给其他数组元素为’\0’

处理字符数组时候,一旦遇到’\0’就表示字符串已经结束,如果字符串有多个’\0’,那么会认为在第一个’\0’之前的是有效字符。

字符串和字符数组最显著的区别,就是字符数组中,如果数组长度等于字符个数,那么是不需要添加’\0’

在计算字符串的长度时,‘\0’是不参加计算的。

如果你在定义的时候,指定字符,那么可以不显示指定字符数组的长度,编译器会自动知道。

只要字符串没有字符,那么系统会自动加上’\0’

如果你一直给字符串赋值,那么strlen是变的,这个一定要在后面注意,这点和java是不一样。

字符串的输入输出

   char a[20];   char b[20];   scanf("%s",a);//使用字符控制符去输入,字符串必须是存放在字符数组中   printf("%s",a);//打印的时候也是直接数组名   gets(b);//传入数组名,这种方法和上面比,每次只能输入一个字符串,上面可以是多个。   puts(b);//输出完成后,会自动换行。

注意如何利用scanf输入多个字符串:

scanf("%s%s",a,c);

一般的在scanf遇到一个%s,就是一次,千万不能理解这个是一次输入两个,那就不对了,不要看他们是同一行。

字符串处理函数

char c1[80]={"sdada"};    char c2[80]={"hsdkjass"};    int i  =0;    //strcat(c1,c2);//将后面的字符串连接到前面来    //后面的字符串可以是数组名,    //也可以是字符串常量,但是字符串1必须是字符串数组名。    //strcpy(c1,c2);//将后面的字符串复制到前面字符数组    //后面的字符串可以是数组名,    //也可以是字符串常量,但是字符串1必须是字符串数组名。    //c1="sdasda";错误的    //c1 = c2;错误的    //int r = strcmp(c1,c2);//字符串比较函数    //返回一个整数值,如果是0,代表两个字符串相等    //如果是正整数,代表前面字符串大    //如果是负整数,代表前面的字符串小。    //比较的实质,是从开始比较每一个字符的ascll    //这两个参数可以是字符数组或者字符常量    //两个字符串之间比较绝对不可以用> < == !=    int t = strlen(c1);    //返回字符数组的实际长度不包含结束标识符。    //sizeof是返回参数的内存空间,也就是字节数。    //该方法的参数可以是字符数组或者字符常量

指针

程序运行时,所有的程序和数据都是放在内存中,内存是以字节为单位的连续的存储空间,每一个内存都有一个编号,称为内存地址。

一个字节就是一个存储单元。

变量的地址是由编译器动态分配的,对用户是无关的。

指针:就是指向某个对象(可能是简单变量、数组、函数)所占用的存储单元的首地址,这里说明一下,一个对象,开辟的空间一定是连续的,所以,指针就是指向这个连续空间的首地址。

指针变量:存放变量地址的变量。

访问类型
  1. 直接访问

直接通过变量名来访问。

  1. 间接访问

先找到存放该变量的地址的变量,先找到地址,在访问。

指针变量定义
int *i_pointer;//表示指向整型变量的指针变量。

其中* 表示定义指针变量,前面的类型,也称基类型,表示指针变量所指向的变量的类型。

指针变量只能指向定义时所规定类型的变量。

不可以将任何非地址的值,赋给指针变量,除了0(NULL)必须是大写。

    int *p;    *p = 0;    *p =NULL;

指针变量定义好了之后,必须要初始化,否则变量值不确定。

指针初值,可以赋3种形式

  1. &变量名
  2. &数组元素
  3. 数组名
    int *p;    int a;    int b[5];    p = &a;    p =b;    p = b[0];

*是间接访问运算符,它是先访问指针变量,然后在访问它指向的变量的值。

指针变量的算术运算。

指针p+n,是指指针p原来指向的数据单元格之后的第n个数据单元格,而数据单元格和数据类型有关。

在这里,我要说明一下,数据存储单元和内存单元的对比。

这里写图片描述

数据存储单元格是人们简化内存单元格的。

   int *p;   int a;   p=&a;   //假如a的地址是2000,则p+1 = 2004   //原因int的数据类型占4个字节

所以在这,你就要理解指针变话p++,就是使p指向下一个空间。

指针的比较

在同一段连续的存储空间,如果p的地址值小于q的地址值,那么结果为1,反之为0。

指针和一维数组关系

数组名就是指针,是数组的首地址,这个叫做静态指针。

    int a[10];    int *p;    p =a;//p = &a[0]两种等价

根据指针运算p+1,就是指向数组中的下一个元素。

利用指针遍历一维数组的两种方法
 for(i=0;i<5;i++){        scanf("%d",p+i);//根据i的变化,改变指针指向的地址    }     for(i=0;i<5;i++){        printf("%d",*(p+i));    }        for(p=a;p<a+5;p++){            scanf("%d",p);//指针初始值指向数组的首地址,指针的地址范围应该是控制数组首地址加上数组的个数,自增改变指针的地址。        }        for(p=a;p<a+5;p++){        printf("%d",*p);    }

在一维数组中

  a[i] =p[i] = p+i = a+i//都表示是指向某一个元素

2维数组指针

从二维数组来看,a是二维数组名,a就代表了整个二维数组的首地址。a+1代表第一行。

a[0]+1,就代表第一列。

故:
//在这里,我们把对二维数组的处理,当成多个1维数组来处理。

a[i][j] = *(a[i]+j)=*(*(a+i)+j)

在二维数组有两个概念

  1. 列地址
a[i][j] = *(a[i]+j)=*(*(a+i)+j)都表示列地址
  1. 行地址
a 代表二维数组首行a+1  第一行  a+2  第二行
  • 行地址前就加*就变为列地址。
  • 列地址前加&就变为行地址。
  • 只有在列地址前加*才能访问该二维数组的值。
二维数组的指针变量
int a[2][2];  int (*p)[2];//指针变量的括号一定不能少  p =a;  int i,j;  for(i =0;i<2;i++){    for(j = 0;j<2;j++){        scanf("%d",(*(p+i)+j));    }  }  for(i =0;i<2;i++){    for(j = 0;j<2;j++){        printf("%d",*(*(p+i)+j));    }  }

字符串指针

用指针变量操作字符串,指针变量指向的是字符串的首地址,也就是第一个字符地址。

  char str[]="helloworld";   char *p;//定义字符串指针   p = str;//指向字符串的第一个字符的首地址   int i = 0;   for(i = 0;*p!='\0';p++){    printf("%c",*p);    printf("%s",p);//注意这种操作打印字符串是通过指向第一个指针的*地址*,这里就不是值了。一直到字符串结束,这种比较方便,后面使用的比较多。   }

字符串指针变量使用的注意点

 char c1[10]="hello"; char *pa; pa="hello"//表示指针变量指向的是字符串的第一个字符的首地址  pa+2//指向字符串的第3个字符地址,指针变量可以指向字符串的任意位置,可以随意改变指针变量的值  c1作为字符串的数组名,可以作为首地址,可以进行加减,但是不能赋给c1,因为数组名是地址常量,不可以改变。(这点和前面使用一样,需要注意)

函数返回值是指针

定义函数,返回类型是指针。

定义类型

数据类型 * 函数名 (参数表)
int *max(){    int i = 0;    int k = 0;    static int data[]={1,2,34,9,0,17,8,7};    for(i=0;i<8;i++){    if(data[i]>data[k]){        k = i;    }    }    return &data[k];}void test19(){   int *p;   p = max();//需要定义的指针变量去接收函数返回值,这里定义的指针变量需要和函数定义的返回类型一致。   printf("%d",*p);}

指向函数的指针

指向函数的指针,实际上就是函数执行的入口,函数名就代表中该函数的入口地址。

数据类型 (* 指针变量名)  (参数表)

对函数的调用

(* 指针变量名) (实参)

例子:

int max1(int data[],int n){   int i = 0;    int k = 0;    for(i=0;i<n;i++){    if(data[i]>data[k]){        k = i;       }    }    return data[k];}void test20(){    int a[4] ={2,9,8,0};    int (*p)(int a[],int n);//定义指针函数    int m = 0;    p = max1;//在此之前,你需要申明一下max1函数,这里我申明了指向函数的入口    m =  (*p)(a,4);//执行函数    printf("%d",m);}

二级指针

定义:一个指针变量存放的是另一个指针变量地址。

   int i = 78;   int *p;   int **pp;//定义二级指针   p = &i;   pp = &p;   printf("%d",i);   printf("%d",*p);   printf("%d",**pp);

指针函数

定义: 数组中的每一个元素都是指针类型。

   char *a[100]={"hello","world"};   int i = 0;   for(i = 0;i<2;i++){    printf("%s",a[i]);//a[0]就是指向第一个数组元素的(首地址)指针,所以直接打印字符串    //在前面说过,如果指针指向的是字符串的首地址,打印出来,则是整个字符串   }

数组指针

定义:指向整个数组的指针。

   int a[4]={1,2,3,4};   int (*p)[4];   p = a;//这个是指向整个数组的指针,这里注意区分之前用的多的是指向数组的第一个元素的指针。  int a[2][3]={1,2,3,4,5,6};  int (*p)[3] = a;//这里的指针是数组中存在每一个元素首地址的指针集合,而这里每一个元素换成一行的首地址,这里需要重点理解一下。为什么可以指向一个二维数组呢,原因很简单,你可以这样理解,二维数组其实,我们可以看成2行的1维数组,p[0]就是指向1,2,3的首地址1,p[1]就是指向2,3,4的首地址2,然后p[0]+2,就是指针移动指向3。  printf("%d",*(p[1]));  printf("%d",*(*(p+1)+1));//访问第二行的第二个元素。

指针tip

在前面我们说过,数组名是静态指针,不可以进行自加自减,但是可以执行a+1等运算操作,注意一下。

结构体

我们前面学习了,可以利用数组进行同一种数据类型的处理,而我们也是有可能把不同的数据类型作为一个整体,这时,就可以选用结构体来处理这种数据。

结构体作为一种数据结构,是不太方便好去遍历,我们可以通过链表去实现对结构体的遍历。链表是可以通过结构体去实现的。

 struct date{    int year;    int months;    int days;  };  struct date birth;//定义一个结构体date的变量  //需要注意的是定义结构体类型,本身不占用存储空间,  //只是说明了结构体组织形式,只有定义结构体;变量,才占用空间。  //在本例中,结构体占的空间,就是3个int所占空间之和。  struct date birth1,birth2,birth3  //定义多个结构体变量,用逗号隔开。  struct date{    int year;    int months;    int days;  }  birthday;//可以在定义结构体类型时,一起定义结构体变量。

下面这是我们处理结构体定义常用方法。利用typeof定义新的结构体类型名代替定义的结构体类型名。

typedef struct date{    int year;    int months;    int days;  }  Date;  Date birthday;//这样定义结构体变量就简单,也好记。struct date birthday两种等价

结构中定义中,可以嵌套结构体变量。

typedef struct date{    int year;    int months;    int days;    struct birthday1;  }  Date;

结构体变量的成员引用操作

.是结构体成员运算符,在所有优先级中是最高的。

 struct StudentDate{     int year;     int month;     int day;    };   struct Student{     int num;     char name[20];     char sex[10];     float score;     struct StudentDate birthday;   };   struct Student s;//定义结构体变量   scanf("%d",&s.num);//如果直接是结构体    //的成员,直接通过.运算符来进行操作   printf("%d",s.num);   scanf("%d",&s.birthday.year);   printf("%d",s.birthday.year);   //如果是内嵌结构体成员,   //则需要通过外部的结构体变量去引   //用内部结构体变量的成员,这里需要注意内部结构体变量已经申明在外部结构体中,不需要在定义了。

结构体变量的初始化

struct StudentDate{     int year;     int month;     int day;    } a={1996,9,10};    struct StudentDate{     int year;     int month;     int day;    };    struct StudentDate a ={199,9,10};//定义结构体变量并赋值
  • 一定不能在结构体内部初始化。
  • 赋值的时候一定要和结构体中定义的顺序一致。
  • 如果结构体中有内嵌,初始化和外部结构体一起初始化,按照顺序即可。

结构体与数组

结构体中成员可以是数组类型

 struct student{     int a[10];   };   struct student s;   scanf("%d",&s.a[1]);   printf("%d",s.a[1]);

结构体数组,即该数组中每一个元素都是结构体类型。

struct student{     int a[10];   };   struct student s[3];//定义了一个包含3个元素   //的数组,并且每一个元素都是结构体类型   scanf("%d",&s[2].a[1]);   printf("%d",s[2].a[1]);

结构体数组初始化:

struct student{     int a[10];   } s[3]={      {12},{22},{4}      };

结构体如何访问数组成员

这里演示的是通过结构体指针去访问,通过结构体变量访问比较简单,自行看。

struct Student {   int num;   char name[20];   float score[5];};p->score[0]

结构体与指针

  1. 结构体成员是指针
struct test{      int data;      int *p;   };   struct test t;   t.data  =100;   int i;   t.p = &i;//通过结构变量   //去调用指针变量去指向一   //个int类型的变量   *t.p = 88;//这个需要注意,之前说过.运算符是优先级最高的。   printf("%d",t.data);   printf("%d",i);
  1. 指向结构体变量的指针
 struct date{   int year;   };   struct date d;   struct date *p;   p=&d;   (*p).year = 1990;   //可能会有人认为为啥这里   //不是p,p只是一个地址,我   //们需要通过p指向的地址值,来操作。   printf("%d",(*p).year);//由于优先级,括号不能少   printf("%d",p->year);//简化操作访问成员操作,不过这个操作符只能和指针一起使用。   printf("%d",d.year);
  1. 指向结构体数组的指针
 struct test{       int s;     } a[2]={     {1},{2}     };     struct test *p;     p = a;//数组名就是首地址     for(;p<a+2;p++){        printf("%d",*p);     }

结构体链表

结构体成语可以指向本结构体类型的指针,可以用这个来构造比较复杂的数据结构体,链表。

链表是由称为节点的元素组成,节点多少根据需要来定。

每一个节点包含:

  1. 数据部分,可以存放多个数据成员。
  2. 指针部分,可以存放下一个节点的地址。

链表结构特点:链表有一个首指针,它指向链表的第一个节点,最后一个节点称为 “表尾”,表尾节点的指针为null。

动态内存分配

malloc:从内存中申请一块指定字节大小的连续空间,返回该存储地址的首地址作为函数的返回值,如果申请失败,说明没有足够的空间可以分配,返回空指针。

   int *p;   p = (int *)malloc(sizeof(int));   //通过该函数动态申请了一个int类型大小   if(p!=null){   *p = 23;   }else{   exit(1);//exit是系统标准函数,作用是关闭   //所有打开文件,并终止程序执行。参数为0是正常结束,非0   //表示不正常结束。   }

由于该函数返回的是void类型的指针,所以需要进行强制类型转换,转换为指针变量所应该指向的数据类型。

内存释放

free()函数。

注意点:

  1. free函数和malloc函数必须配对使用,申请的内存空间,不用的时候一定要释放。
  2. 加入两个指针同时指向同一个地址,如果只释放其中一个指针,这时另外一个指针就不能访问这块存储区。

共用体

有时,我们希望在不同的时刻把不同的类型数据存放到同一个内存单元中。

共用体的定义
union un{   float f;   int i ;   char c;   };//定义共用体   union un u;//定义共用体变量   union un1{   float f;   int i ;   char c;   }u;//定义共用体变量和类型

注意点:

  1. 尽管共用体与结构体在定义上类似,但是在内存分配上有本质的区别。
  2. 共用体成员占相同的起始地点,所占内存长度等于最长的成员所占内存长度。
共用体的访问对象

通过.运算。

 u.c = 'a';

如果是定义的是指针,那么同样可以通过—>去访问对象。

  • 由于共用体各个成员都共用一段存储空间,所以在任意的时刻,只能有一种数据类型存放在共用体变量中,也就是说任意一个时刻,只有一个成员有意义。
  • 在引用共用体变量时,必须保证其存储类型的一致性,在一次程序运行时,一个成员操作了申明类型,在下一次中,还必须是这种类型。
  • 共用体不能作为函数参数
  • 共用体不能初始化,原因很简单,如果初始化的话,那不就是说他们同时有意义,这不符合共合体的使用。
结构体和共用体的联合使用

共用体可以出现在结构体中,结构体也可以出现在共用体中。

union un{   int fivescore;   float hunscore;};struct Student{   int num;   char name[20];   char sex;   int type;   union un scrore;//这里将共用体定义在结构体中,需要定义共用体变量。(如果这里是定义结构体,那么这里就需要定义结构体变量)};  p1->scrore.hunscore  = hunscore1;//访问内部共用体变量的时候,就需要注意,定义结构体指针,通过—>来访问结构体的变量,因为这时得到的是共用体的变量,通过共用体变量名访问成员,就必须是.运算符。

枚举

枚举类,一个变量在很小的范围内取值,则可以使用枚举类。

    enum Bool{     Flase,True   };//定义枚举类型   enum Bool bool;//定义枚举变量   enum Bool1{     Flase1,True1   } bool1; //在定义枚举类型和枚举变量   printf("%d",True);//打印枚举量的值,虽然定义和结构体很类似,但是访问成员不是通过.运算。

注意点:

  • 枚举元素是常量,有固定的数值,按枚举的顺序分别是 整数0,1,2,3;不能被用作变量,即不可以出现在赋值号的左边。
 True = 1;//是不允许的
  • 不能有两个元素相同的枚举元素,枚举元素也不能与其他变量同名。
  • 枚举元素作为常数处理,遇到枚举元素,编译器会将其中第一个元素赋值为0,然后依次叠加。自己可以修改为枚举元素指定值,然后排在该枚举元素后面的值,将自动一次叠加1。

typedef

用于用户自己定义类型说明符。

typedef int INT;  INT a  = 5;//等价于int a =5  typedef char NAME[20];  NAME a1;//等价于 char a1[20];  typedef struct Student{      int num;      float score;  } S;  S student;//等价于struct Student student  typedef char *p;  p p1;//等价于 char * p1

这个使用你只需要,找到原始的元素定义的变量,直接用这个变量来简化申明你自己定义的变量。

函数的申明与调用

函数声明

c语言编译,是从上到下,如果被调函数不在调用函数之前,则必须显示申明,否则报错。

函数类型 被调函数名(形参表列)//这种必须包括形参类型、变量名函数类型 被调函数名(形参类型表列)//这种只是形参类型,没有变量名

有些标准的库函数,只需要导入头文件即可。

参数传递

分类:

  1. 值传递
  2. 地址传递

当形参为简单变量时,在函数调用过程中,数据只能由实参传给形参,而不能由形参传回给实参,这种数据传递方式是单向,无论形参如果修改值,都不会影响实参的值。

数组作为参数传递:

  1. 当数组元素即元素下标作为参数传递,数组元素都是简单元素,形参和实参占用不同的存储空间,实参与形参之间的数据传递是单向值传递,不会改变原有数组的元素值。
  2. 当用数组名作为参数传递,数组名代表元素的首地址,这时,实参与形参共用一块内存空间。形参中的数组值改变,会影响原有的数组,这种是地址传递。要实现地址传递,形参和实参都必须是类型相同 的数组名,后面用指针作为函数传递,也是地址传递。

局部变量、全局变量

局部变量:作用域仅限于函数内有效,离开该函数则没有用。

  • 在参数传递时,形参就是该调用函数的局部变量。
  • 在不同的函数中,可以使用相同的变量名,互相不干扰。

全局变量:是指定义在函数外的变量,作用从定义的位置到本源程序文件尾。

变量的存储类别

变量存储方式:

  1. 静态存储方式:是指在程序运行期间分配固定的存储空间,
  2. 动态存储方式:是指在程序运行期间根据需要进行动态分配存储空间。每执行完程序一次,就会释放变量空间

变量存储类别

  1. auto变量。在c语言中饭时未加存储类别的变量均视为自动变量。自动变量属于动态存储,只有在被调用的时候才分配内存单元,程序结束后,立即释放存储单元。
  2. static变量。又称之为静态变量。在函数局部定义中的变量,函数执行,该值仍然保留,等待下次该函数执行,除非该函数在也不执行,就释放。

    静态变量在编译时,只赋初值一次,赋值为0。而自动变量,每次执行完函数,都会重新赋值。自动变量未赋值,它的值是不确定的。
    虽然静态变量的值,函数执行结束,变量空间未释放,但静态变量不可以被其他函数调用。

  3. 寄存器变量。如果一个函数频繁的使用某个变量计算,那么就可以使用寄存器变量。寄存器变量,只能给自动变量和形参定义,不可以将全局、静态变量定义为寄存器变量。由于计算机的寄存器数目多,所以不宜定义太多寄存器变量。

  4. extern(外部变量),这个可以类比是全局变量,但是全局变量是在该定义之后才可以使用该变量,那么在之前使用,则需要用extern申明,就可以当成全局变量使用,否则会产生语法错误。