《C语言程序设计教程》(一)
来源:互联网 发布:初学者模拟炒股软件 编辑:程序博客网 时间:2024/06/06 01:17
- 标识符规则
- 常量变量
- 变量的初始化
- 数据类型
- 实型数据
- 字符型数据
- 基本表达式和运算符
- sizeof
- 类型强制转化
- printf格式控制字符
- 附加格式符
- putchar
- 标准输入
- scanf调用注意点
- getchar
- 条件运算条件表达式
- if条件
- for
- breakcontinue
- 判断是否是素数
- 数组
- scanf函数
- getchar方法
- 字符数组
- 字符串
- 字符串的输入输出
- 字符串处理函数
- 指针
- 访问类型
- 指针变量定义
- 指针的比较
- 指针和一维数组关系
- 利用指针遍历一维数组的两种方法
- 2维数组指针
- 二维数组的指针变量
- 字符串指针
- 字符串指针变量使用的注意点
- 函数返回值是指针
- 指向函数的指针
- 二级指针
- 指针函数
- 数组指针
- 指针tip
- 结构体
- 结构体变量的成员引用操作
- 结构体变量的初始化
- 结构体与数组
- 结构体如何访问数组成员
- 结构体与指针
- 结构体链表
- 动态内存分配
- 内存释放
- 共用体
- 共用体的定义
- 共用体的访问对象
- 结构体和共用体的联合使用
- 枚举
- typedef
- 函数的申明与调用
- 参数传递
- 局部变量全局变量
- 变量的存储类别
标识符规则
- 标识符只能由字母、数字、下划线组成。
- 标识符的有效长度是1-255。
- 标识符的第一个字符必须是字母或者数字。
- 标识符在大小写是区分。
- 标识符不能与c的关键字相同。
常量、变量
int c= 7;#define PAI = 3.1415926;//常量的标识符全好是大写。
变量的初始化
可以多个同类型的一起赋值
int c= 7,b = 6;
数据类型
实型数据
也称为浮点数。两种表现形式:
- 十进制小数
- 指数形式
double c = 1.6e3;//这里用大小的e无所谓 一般形式:aEn a为十进制数,n为阶码,表示指数,必须是十进制整数,正负都可以。
需用的注意以下几点:
- 阶码之前必须有十进制的数。
- 指数不能为小数。
在实型计算中,不区分单精度还是双精度,都按照double,除非,你在数字后面指定了f或F,则认为是float。
double 提供16位有效数字,就是7位整数。
float提供7位有效数字,就是16位整数。
字符型数据
字符常量是用单引号括起来的字符。
- 只有用单引号括起来的才是字符常量,用双引号或者其他符号括起来不是字符常量。
- 字符常量只能是单个字符,不能是多个,转义的除外。
- 字符常量以ASCLL码存储,范围0-255,字符常量是以ASCLL
等价的整数值就行运算。
转义字符
是一种特殊的字符常量,以\开头,有特定的含义。
\n 回车换行
\t 横跳下一个制表符
\b 退格
\r 回车
\f 走纸换页
\ 反斜线\
\’ 单引号
\” 双引号
字符变量
char o = 'a';
一个字符变量占一个字节的分配空间。
一个中文汉字=两个字符,占2个字节。
字符串常量
字符串常量是由一对双括号括起来,系统会自动在每个字符串结束后面加一个字符串结束标志’\0’。
字符常量和字符串常量区别
- 字符串由单括号括起来,字符串常量是由双括号括起来的
- 字符串只能是单个字符(除转义外),字符串常量可以含0个或多个。
在c语言中,可以把一个字符常量赋值给字符变量,但是不能把一个字符串常量赋值给字符串变量,因为在
c中,没有定义相应的字符串变量,在后面会讲到用字符数组来存放一个字符串常量。
字符串常量的字节数,是字符串的字符个数+1,因为还有一个字符串结束标识符也占一个字节。
基本表达式和运算符
在c语言中一些基本的,我就不讲。
sizeof是用来结束数据的字节数。
/:是除法运算,如果参加运算的都是整型,那么结果就是整型,舍去小数;但是如果参加的运算有一个是实型,那么结果就是double。
%:求余运算,要求参加运算的量都是整型,然后取两数的余数。
sizeof
这个功能是求数据在内存中所占的字节数。
int a = sizeof(10); printf("%d",a);
类型强制转化
double c = (double)(a+b);
printf格式控制字符
- %d 以十进制输出带符号整数,不包含正数符号。
- %o 以八进制输出无符号的整数,不输出前缀0。
- %x 以十六进制输出无符号整数,不输出OX。
- %u 以十进制输出无符号整数。
- %f 以小数形式输出单、双精度实数。
- %e 以指数形式输出单、双精度实数。
- %c 输出单个字符。
- %s 输出字符串。
附加格式符
- %-d %-c %-f 结果是左对齐,默认不加是右对齐。
- %+d 输出数字的时候带正负号。
- 空格 在输出正数时前面加空格,输出负数前面加负号。
- %ld %lf 用来输入长整型或者双精度数字。
- %md 代表整数输出几位数字。
- %m.nf 代表浮点数小数点后面n位。
putchar
可以用来输入字符常量和字符变量。
putchar('a');
标准输入
scanf(“格式控制字符”,地址表列);//地址列表中给出的各变量的地址,地址是通过取地址符&后面跟变量名来获取的。
scanf调用注意点
- 在输入数据的时候,两个数据一般用空格、enter、tab分开。
- 如果在各式控制字符中出现非格式控制字符,你需要在控制台也要原样输进去。
- 在输入数据的时候,不要指定精度。
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是返回参数的内存空间,也就是字节数。 //该方法的参数可以是字符数组或者字符常量
指针
程序运行时,所有的程序和数据都是放在内存中,内存是以字节为单位的连续的存储空间,每一个内存都有一个编号,称为内存地址。
一个字节就是一个存储单元。
变量的地址是由编译器动态分配的,对用户是无关的。
指针:就是指向某个对象(可能是简单变量、数组、函数)所占用的存储单元的首地址,这里说明一下,一个对象,开辟的空间一定是连续的,所以,指针就是指向这个连续空间的首地址。
指针变量:存放变量地址的变量。
访问类型
- 直接访问
直接通过变量名来访问。
- 间接访问
先找到存放该变量的地址的变量,先找到地址,在访问。
指针变量定义
int *i_pointer;//表示指向整型变量的指针变量。
其中* 表示定义指针变量,前面的类型,也称基类型,表示指针变量所指向的变量的类型。
指针变量只能指向定义时所规定类型的变量。
不可以将任何非地址的值,赋给指针变量,除了0(NULL)必须是大写。
int *p; *p = 0; *p =NULL;
指针变量定义好了之后,必须要初始化,否则变量值不确定。
指针初值,可以赋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)
在二维数组有两个概念
- 列地址
a[i][j] = *(a[i]+j)=*(*(a+i)+j)都表示列地址
- 行地址
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]
结构体与指针
- 结构体成员是指针
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);
- 指向结构体变量的指针
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);
- 指向结构体数组的指针
struct test{ int s; } a[2]={ {1},{2} }; struct test *p; p = a;//数组名就是首地址 for(;p<a+2;p++){ printf("%d",*p); }
结构体链表
结构体成语可以指向本结构体类型的指针,可以用这个来构造比较复杂的数据结构体,链表。
链表是由称为节点的元素组成,节点多少根据需要来定。
每一个节点包含:
- 数据部分,可以存放多个数据成员。
- 指针部分,可以存放下一个节点的地址。
链表结构特点:链表有一个首指针,它指向链表的第一个节点,最后一个节点称为 “表尾”,表尾节点的指针为null。
动态内存分配
malloc:从内存中申请一块指定字节大小的连续空间,返回该存储地址的首地址作为函数的返回值,如果申请失败,说明没有足够的空间可以分配,返回空指针。
int *p; p = (int *)malloc(sizeof(int)); //通过该函数动态申请了一个int类型大小 if(p!=null){ *p = 23; }else{ exit(1);//exit是系统标准函数,作用是关闭 //所有打开文件,并终止程序执行。参数为0是正常结束,非0 //表示不正常结束。 }
由于该函数返回的是void类型的指针,所以需要进行强制类型转换,转换为指针变量所应该指向的数据类型。
内存释放
free()函数。
注意点:
- free函数和malloc函数必须配对使用,申请的内存空间,不用的时候一定要释放。
- 加入两个指针同时指向同一个地址,如果只释放其中一个指针,这时另外一个指针就不能访问这块存储区。
共用体
有时,我们希望在不同的时刻把不同的类型数据存放到同一个内存单元中。
共用体的定义
union un{ float f; int i ; char c; };//定义共用体 union un u;//定义共用体变量 union un1{ float f; int i ; char c; }u;//定义共用体变量和类型
注意点:
- 尽管共用体与结构体在定义上类似,但是在内存分配上有本质的区别。
- 共用体成员占相同的起始地点,所占内存长度等于最长的成员所占内存长度。
共用体的访问对象
通过.运算。
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语言编译,是从上到下,如果被调函数不在调用函数之前,则必须显示申明,否则报错。
函数类型 被调函数名(形参表列)//这种必须包括形参类型、变量名函数类型 被调函数名(形参类型表列)//这种只是形参类型,没有变量名
有些标准的库函数,只需要导入头文件即可。
参数传递
分类:
- 值传递
- 地址传递
当形参为简单变量时,在函数调用过程中,数据只能由实参传给形参,而不能由形参传回给实参,这种数据传递方式是单向,无论形参如果修改值,都不会影响实参的值。
数组作为参数传递:
- 当数组元素即元素下标作为参数传递,数组元素都是简单元素,形参和实参占用不同的存储空间,实参与形参之间的数据传递是单向值传递,不会改变原有数组的元素值。
- 当用数组名作为参数传递,数组名代表元素的首地址,这时,实参与形参共用一块内存空间。形参中的数组值改变,会影响原有的数组,这种是地址传递。要实现地址传递,形参和实参都必须是类型相同 的数组名,后面用指针作为函数传递,也是地址传递。
局部变量、全局变量
局部变量:作用域仅限于函数内有效,离开该函数则没有用。
- 在参数传递时,形参就是该调用函数的局部变量。
- 在不同的函数中,可以使用相同的变量名,互相不干扰。
全局变量:是指定义在函数外的变量,作用从定义的位置到本源程序文件尾。
变量的存储类别
变量存储方式:
- 静态存储方式:是指在程序运行期间分配固定的存储空间,
- 动态存储方式:是指在程序运行期间根据需要进行动态分配存储空间。每执行完程序一次,就会释放变量空间
变量存储类别
- auto变量。在c语言中饭时未加存储类别的变量均视为自动变量。自动变量属于动态存储,只有在被调用的时候才分配内存单元,程序结束后,立即释放存储单元。
static变量。又称之为静态变量。在函数局部定义中的变量,函数执行,该值仍然保留,等待下次该函数执行,除非该函数在也不执行,就释放。
静态变量在编译时,只赋初值一次,赋值为0。而自动变量,每次执行完函数,都会重新赋值。自动变量未赋值,它的值是不确定的。
虽然静态变量的值,函数执行结束,变量空间未释放,但静态变量不可以被其他函数调用。寄存器变量。如果一个函数频繁的使用某个变量计算,那么就可以使用寄存器变量。寄存器变量,只能给自动变量和形参定义,不可以将全局、静态变量定义为寄存器变量。由于计算机的寄存器数目多,所以不宜定义太多寄存器变量。
extern(外部变量),这个可以类比是全局变量,但是全局变量是在该定义之后才可以使用该变量,那么在之前使用,则需要用extern申明,就可以当成全局变量使用,否则会产生语法错误。
- 《C语言程序设计教程》(一)
- C语言程序设计笔记(一)
- C语言程序设计入门(一)
- C语言程序设计(一)-基础知识
- C语言程序设计教程
- C语言程序设计教程1009
- C语言程序设计学习日志(一)
- C语言程序设计【一】
- C语言程序设计<一>
- C语言程序设计谭浩强版 一
- C语言程序设计教程_函数
- 1052: C语言程序设计教程(第三版)课后习题11.5
- 1052: C语言程序设计教程(第三版)课后习题11.5
- 1001: C语言程序设计教程(第三版)课后习题1.5
- 1003: C语言程序设计教程(第三版)课后习题3.7
- 1005: C语言程序设计教程(第三版)课后习题4.9
- 1007: C语言程序设计教程(第三版)课后习题5.5
- 1009: C语言程序设计教程(第三版)课后习题5.7
- UVA 10336 Rank the Languages
- JavaWeb: 报错信息The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path
- 单链表与双向链表
- mybatis新增处理逗号
- extern与头文件(*.h)的区别和联系
- 《C语言程序设计教程》(一)
- 神经机器翻译(Neural Machine Translation)系列教程
- jquery-ui实现bootstrap的modal拖拽功能,弹窗头部拖拽
- CSDN-markdown编辑器用法
- 合并两个排序的链表
- matlab画图程序整理
- 数据库索引的实现原理
- LeetCode 290. Word Pattern
- [LeetCode] Roman to Integer