0
点赞
收藏
分享

微信扫一扫

C语言简概

晴儿成长记 2022-04-16 阅读 31
c语言

一.数据类型

最常用的整型, 实型与字符型(char,int,float,double):
在这里插入图片描述

整型数据是指不带小数的数字(int、short int、long int、unsigned int、unsigned short int、unsigned long int):
在这里插入图片描述

二.运算符,表达式和语句
 算术运算符
在这里插入图片描述

注:除法运算中
1、如果相除的两个数都是整数的话,则结果也为整数,小数部分省略,如30/10 = 3;
2、而两数中有一个为小数,结果则为小数,如:10.0/2 = 5.000000。
注:取余运算中
该运算只适合用两个整数进行取余运算,如:23%7 = 2,而23.0%7则是错误的;运算后的符号取决于被模数的符号,如(-23)%7 = -2;而23%(-7) = 2;
注:自增自减运算符(经常使用在循环语句里)
在这里插入图片描述

 赋值运算符
1、简单赋值运算符—“=”
2、简单赋值符“=”之前加上其它运算符构成(+=、-=、*=、/=、%=)
例:a += 5等价于a = a+5。
 关系运算符
在这里插入图片描述

注:关系表达式的值是真和假,在C语言中用整型的1和0表示。
 逻辑运算符
逻辑运算的值也是分为真和假,C语言中用整型的1和0来表示。其求值规则如下:
1、与运算 &&
参与运算的两个变量都为真(1)时,结果才为真,否则为假(0)。例如:10>=10 && 10>5 ,运算结果为真;
2、或运算 ||
参与运算的两个变量只要有一个为真,结果就为真。 两个量都为假时,结果为假。例如:10>=10||5>10,运算结果为真;
3、非运算 !
参与运算的变量为真时,结果为假;参与运算量为假时,结果为真。例如:!(5>10),运算结果为真。
 三目运算符
C语言中的三目运算符:?:,其格式为:表达式1 ? 表达式2 : 表达式3;
执行过程是:
先判断表达式1的值是否为真,如果是真的话执行表达式2;如果是假的话执行表达式3。

三.循环
1、while循环
While(表达式)
{
代码
}
其中表达式表示循环条件,代码为循环体。
while语句的语义是:计算表达式的值,当值为真(非0)时,执行循环体代码。
while语句中的表达式一般是关系表达或逻辑表达式,当表达式的值为假时不执行循环体,反之则循环体一直执行。
一定要记着在循环体中改变循环变量的值,否则会出现死循环(无休止的执行)。
循环体如果包括有一个以上的语句,则必须用{}括起来,组成复合语句。
2、do-while循环
do
{
代码
}while(表达式);//注这里有分号
do-while循环语句的语义是: 它先执行循环中的执行代码,然后再判断while中表达式是否为真,如果为真则继续循环;如果为假,则终止循环。因此,do-while循环至少要执行一次循环语句。
3、for循环
for(表达式1;表达式2;表达式3)
{
代码
}
它的执行过程如下:

  1. 执行表达式1,对循环变量做初始化;
  2. 判断表达式2,若其值为真(1),则执行for循环体中执行代码,然后向下执行;若其值为假(0),则结束循环;
  3. 执行表达式3,(i++)等对于循环变量进行操作的语句;
  4. 执行for循环中执行代码块后执行第二步;第一步初始化只会执行一次。
  5. 循环结束,程序继续向下执行。
    for循环中:
    表达式1是一个或多个赋值语句,它用来控制变量的初始值;
    表达式2是一个关系表达式,它决定什么时候退出循环;
    表达式3是循环变量的步进值,定义控制循环变量每循环一次后按什么方式变化。
    这三部分之间用分号 ; 分开。
    注:
    for循环中的“表达式1、2、3”均可不写为空,但两个分号( ; ; )不能缺省。
    省略“表达式1(循环变量赋初值)”,表示不对循环变量赋初始值。
    省略“表达式2(循环条件)”,不做其它处理,循环一直执行(死循环)。
    省略“表达式3(循环变量增减量)”,不做其他处理,循环一直执行(死循环)。
    表达式1可以是设置循环变量的初值的赋值表达式,也可以是其他表达式。
    表达式1和表达式3可以是一个简单表达式也可以是多个表达式以逗号分割。
    表达式2一般是关系表达式或逻辑表达式,但也可是数值表达式或字符表达式,只要其值非零,就执行循环体。
    各表达式中的变量一定要在for循环之前定义。
    四.分支和跳转
    1、if条件语句
    If(表达式)
    {
    代码
    }
    2、if-else语句
    If(表达式)
    {
    代码1
    }
    else
    {
    代码 2
    }
    语义是: 如果表达式的值为真,则执行代码块1,否则执行代码块2
    3、多重if-else语句
    If(表达式)
    {
    代码1
    }

    else if(表达式m)
    {
    代码m
    }

    else
    {
    代码n
    }
    4、嵌套if-else语句
    If(表达式)
    {
    If(表达式)
    {
    代码
    }
    else
    {
    代码
    }
    }
    else
    {
    代码
    }
    五.函数
    1、一个源程序由多个函数组成。
    2、C程序的执行从main()函数开始;
    3、所有函数都是平行的;
    4、函数分类;可以分为标准和自定义,还可以分为有参函数和无参函数。
    函数定义的一般形式:
    1、类型标志符 函数名()
    {undefined
    声明部分
    语句
    }
    2、类型标志符 函数名(形式参数列表)
    {undefined
    声明部分
    语句
    }
    形参和实参的说明:
    (1) 在定义函数中指定的形参,在未出现函数调用时,他们并不占用内存中的存储单元,只有发生调用时,才会分配内存;
    (2) 实参可以是常量,变量或者表达式,有时传递的时地址;
    (3) 在被定义中,形参必须指定类型;
    (4) 实参与形参的类型应相同或赋值兼容;
    (5) C语言规定,实参变量对形参变量的数据传递是“值传递”,即单向传递,只有实参传递给形参,而不能由形参传递给实参。
    函数的返回值:
    希望通过函数调用使主调函数得到一个确定的值。
    1、函数的返回值是通过函数中的return语句获取的。
    2、函数值的类型;
    3、如果函数值的类型和return语句中表达式的值不一样,则以函数类型为准。
    4、如果调用函数中没有return语句,并不带回一个确定的用户需要的值,函数不是不带回值,而只是不带回有用的值,带回一个不确定的值。
    5、如不需要带回任何值,用void。
    函数的调用:
    调用方式:1、函数语句;2、函数表达式;3、函数参数。
    局部变量和全局变量:
    1、局部变量,在一个函数内部定义的变量称为内部变量,它只是在本函数范围内的有效,主函数也不能使用其它函数中定义的变量;不同函数中可以使用相同的名字的变量,他们代表不同的对象,互不干扰;形式参数也是局部变量;在一个函数内部,可以在复合语句中定义变量,这些变量只在本复合语句中有效,这种复合句也可以称为“分程序”或“程序块”;
    2、全局变量,在函数之外定义的变量称为外部变量,全局变量可以增加函数间数据联系的渠道,一般不再必要时不要使用,他在程序的全部执行过程中占用存储单元,是函数的通用性,使用全局变量会使程序的清晰性降低。还要注意若果同一源文件中,外部变量和局部变量同名,则在局部变量作用范围内,外部变量被“屏蔽”,不起任何作用。
    变量的存储类别:
    (变量值存储时间)动态存储方式,在程序运行期间进行分动态的分配存储空间的方式,静态存储方式是指在程序运行期间分配固定的存储空间的方式;存储空间分为程序区、静态存储区和动态存储区;全局变量全部放在静态存储区中,程序开始时分配空间,完毕时释放;动态存储区中存放以下数据:
    1、函数形式参数;
    2、自动变量;
    3、函数调用时的现场保护和返回地址;
    在C语言中每个变量和函数都有两个属性,是数据类型和数据存储类型,存储类别是数据在内存中存储的方式。
    存储方式分为静态和动态存储类,具体包含有四种:
    自动的(auto);
    静态的(static);
    寄存器的(register);
    外部的(extern),
    如果不加以声明,就自认为是auto型就会自动分配存储空间属于动态存储方式。
    static声明局部变量是在函数调用结束后不消失而保留原值,即占用存储单元不释放,在下一次调用该函数时,该变量已有值,就是上次函数调用结束时的值。其中需要说明的是在定义局部变量不赋初值的话,则静态局部变量编译时自动赋值为0或者空字符,虽然静态局部变量在函数调用结束后仍然存在,但是其他函数不能引用它的。静态局部变量主要用在当初始化后,变量只是被引用而不改变其值。
    register变量是C语言中允许将局部变量的值放在CPU中的寄存器中需要时直接从寄存器中取出来参加运算,不必再到内存中提取,但是计算机系统中寄存器数量有限,不能任意定义任意多的存储器,局部静态变量不能定义为寄存器变量。
    extern声明外部变量,用以扩展外部变量的作用域。在一个文件中,如果定义之前的函数想引用该外部变量,则应该在引用之前用关键字extern对该变量做外部变量声明。在多文件中,也可以采用extern声明的办法进行外部变量声明。
    有时希望某些局部变量只限于被本文件引用,而不能被其他文件引用,这时就可以采用在定义外部变量时外加一个static,这在程序模块化设计中加强了通用性。static来声明一个变量的作用有二个,一个是在声明对局部变量时。则为该变量分配的空间在整个程序执行期间始终存在;一个是在对全局变量声明中,该变量的作用域仅限于本文件模块操作。注意:这些方法同样适用于函数的声明。
    七.结构体,联合体(重要)
    结构体(struct)是一个或多个变量的集合,这些变量可能为不同的类型,为了处理的方便而将这些变量组织在一个名字之下。由于结构体将一组相关变量看作一个单元而不是各自独立的实体,因此结构体有助于组织复杂的数据,特别是在大型的程序中。

共用体(union),也称为联合体,是用于(在不同时刻)保存不同类型和长度的变量,它提供了一种方式,以在单块存储区中管理不同类型的数据。
结构体 / struct
结构体的定义
声明一个结构体类型的一般形式为:
struct 结构体名 {
成员列表
};
结构体变量(3种方式)

  1. 先声明结构体类型,再定义变量名
  2. 在声明类型的同时定义变量
    struct 结构体名 {
    成员列表
    } 变量名列表;
  3. 直接定义结构体类型变量其省略了结构体名
    struct {
    成员列表
    } 变量名列表;
    共用体
    union 共用体名 {
    成员列表
    } 变量

八.指针(重要)
指针是指向一片内存空间的地址,指针变量是变量,是存放一片内存空间首地址的变量,我们一般所说的指针都是指针变量。
指针的定义及赋值:
类型说明 *变量名  列如 int *p;
区别 int *p=NULL 与 *p=NULL
int p=NULL; //定义指针变量p,并且同时将p的值设置为0x00000000,不是把p的值设置为0x0000000,这个过程叫做初始化
int *p;p=NULL; //定义指针变量p,将p的值设置为NILL,即给p所指向的内存赋值NULL,但是p所指的内存可能是非法的,编译可能会显示内存访问错误,那么做出如下修改,给它一块合法的内存。
int i=10;int *p=&i;*p=NULL; //这时i中的值由10变成了0,而p值本身没变,即内存地址没有改变
指针的大小:
int *P;sizeof§; //指针的大小根据计算机的位数确定,32位机大小为4个字节,64位机大小为8个字节。
指针运算:
需要注意的是指针的类型,+1加的是一个指针类型的大小。
int a[10];int *p=&a; //+1,加了sizeof(int)*1个字节,而不是加sizeof(int[10])*1个字节
指针的使用类型
指针形式
数组形式:
int a[10];int *P=a;
p[0]=1; //指针的数组形式
*(p+1)=2; //指针的指针形式
通过指针修改内容的汇编过程
1.找到指针变量的地址
2.通过指针变量的地址,找到内容的地址
3.通过地址找到内容
4.修改内容
九.宏定义
1.基本使用
宏定义的基本语法:#define 宏名 宏体
#表示是预处理命令
define是宏命令
宏名:是符合C语言变量规则的名字,一般使用大写表示
宏体:“替换文本”可以是任意常数、表达式、字符串等
预处理会在程序进行编译之前进行处理,而宏便是在预处理的时候处理的,在后面程序中使用到宏时程序会一模一样的将宏体等效替换。
宏也分为带参宏和无参宏:
①带参宏:#define MIN(x,y) x<y?x:y
②无参宏:#define PI 3.1415926
宏定义的优点:
①方便程序修改,当我们在程序中需要多次使用某一个变量的时候,把他定义成一个宏便不用同时修改多处地方了。
②提高程序运行效率。宏定义是在预处理期间处理的,而函数是在编译期间处理的。这个区别带来的实质差异是:宏定义最终是在调用宏的地方把宏体原地展开,而函数是在调用函数处跳转到函数中去执行,执行完后再跳转回来。
注:宏定义和函数的最大差别就是:宏定义是原地展开,因此没有调用开销;而函数是跳转执行再返回,因此函数有比较大的调用开销。所以宏定义和函数相比,优势就是没有调用开销,没有传参开销,所以当函数体很短(尤其是只有一句话时)可以用宏定义来替代,这样效率高。

带参宏和带参函数的一个重要差别就是:宏定义不会检查参数的类型,返回值也不会附带类型;而函数有明确的参数类型和返回值类型。当我们调用函数时编译器会帮我们做参数的静态类型检查,如果编译器发现我们实际传参和参数声明不同时会报警告或错误。
注:用函数的时候程序员不太用操心类型不匹配因为编译器会检查,如果不匹配编译器会警告(但是实际测试并没有警告,理论上是有的);用宏的时候程序员必须很注意实际传参和宏所希望的参数类型一致,否则可能编译不报错但是运行有误(一般所希望的是整型数据类型,不然结果一般会出错。

缺点:
①由于是直接嵌入的,代码相对多一点。
②嵌套定义过多可能会影响程序的可读性,而且很容易出错,不容易调试。
③对带参的宏而言,由于是直接替换,并不会检查参数是否合法,存在安全隐患。
第一次内容(4.17前完成)
一.数据类型

最常用的整型, 实型与字符型(char,int,float,double):

整型数据是指不带小数的数字(int、short int、long int、unsigned int、unsigned short int、unsigned long int):

二.运算符,表达式和语句
 算术运算符

注:除法运算中
1、如果相除的两个数都是整数的话,则结果也为整数,小数部分省略,如30/10 = 3;
2、而两数中有一个为小数,结果则为小数,如:10.0/2 = 5.000000。
注:取余运算中
该运算只适合用两个整数进行取余运算,如:23%7 = 2,而23.0%7则是错误的;运算后的符号取决于被模数的符号,如(-23)%7 = -2;而23%(-7) = 2;
注:自增自减运算符(经常使用在循环语句里)

 赋值运算符
1、简单赋值运算符—“=”
2、简单赋值符“=”之前加上其它运算符构成(+=、-=、*=、/=、%=)
例:a += 5等价于a = a+5。
 关系运算符

注:关系表达式的值是真和假,在C语言中用整型的1和0表示。
 逻辑运算符
逻辑运算的值也是分为真和假,C语言中用整型的1和0来表示。其求值规则如下:
1、与运算 &&
参与运算的两个变量都为真(1)时,结果才为真,否则为假(0)。例如:10>=10 && 10>5 ,运算结果为真;
2、或运算 ||
参与运算的两个变量只要有一个为真,结果就为真。 两个量都为假时,结果为假。例如:10>=10||5>10,运算结果为真;
3、非运算 !
参与运算的变量为真时,结果为假;参与运算量为假时,结果为真。例如:!(5>10),运算结果为真。
 三目运算符
C语言中的三目运算符:?:,其格式为:表达式1 ? 表达式2 : 表达式3;
执行过程是:
先判断表达式1的值是否为真,如果是真的话执行表达式2;如果是假的话执行表达式3。

三.循环
1、while循环
While(表达式)
{
代码
}
其中表达式表示循环条件,代码为循环体。
while语句的语义是:计算表达式的值,当值为真(非0)时,执行循环体代码。
while语句中的表达式一般是关系表达或逻辑表达式,当表达式的值为假时不执行循环体,反之则循环体一直执行。
一定要记着在循环体中改变循环变量的值,否则会出现死循环(无休止的执行)。
循环体如果包括有一个以上的语句,则必须用{}括起来,组成复合语句。
2、do-while循环
do
{
代码
}while(表达式);//注这里有分号
do-while循环语句的语义是: 它先执行循环中的执行代码,然后再判断while中表达式是否为真,如果为真则继续循环;如果为假,则终止循环。因此,do-while循环至少要执行一次循环语句。
3、for循环
for(表达式1;表达式2;表达式3)
{
代码
}
它的执行过程如下:

  1. 执行表达式1,对循环变量做初始化;
  2. 判断表达式2,若其值为真(1),则执行for循环体中执行代码,然后向下执行;若其值为假(0),则结束循环;
  3. 执行表达式3,(i++)等对于循环变量进行操作的语句;
  4. 执行for循环中执行代码块后执行第二步;第一步初始化只会执行一次。
  5. 循环结束,程序继续向下执行。
    for循环中:
    表达式1是一个或多个赋值语句,它用来控制变量的初始值;
    表达式2是一个关系表达式,它决定什么时候退出循环;
    表达式3是循环变量的步进值,定义控制循环变量每循环一次后按什么方式变化。
    这三部分之间用分号 ; 分开。
    注:
    for循环中的“表达式1、2、3”均可不写为空,但两个分号( ; ; )不能缺省。
    省略“表达式1(循环变量赋初值)”,表示不对循环变量赋初始值。
    省略“表达式2(循环条件)”,不做其它处理,循环一直执行(死循环)。
    省略“表达式3(循环变量增减量)”,不做其他处理,循环一直执行(死循环)。
    表达式1可以是设置循环变量的初值的赋值表达式,也可以是其他表达式。
    表达式1和表达式3可以是一个简单表达式也可以是多个表达式以逗号分割。
    表达式2一般是关系表达式或逻辑表达式,但也可是数值表达式或字符表达式,只要其值非零,就执行循环体。
    各表达式中的变量一定要在for循环之前定义。
    四.分支和跳转
    1、if条件语句
    If(表达式)
    {
    代码
    }
    2、if-else语句
    If(表达式)
    {
    代码1
    }
    else
    {
    代码 2
    }
    语义是: 如果表达式的值为真,则执行代码块1,否则执行代码块2
    3、多重if-else语句
    If(表达式)
    {
    代码1
    }

    else if(表达式m)
    {
    代码m
    }

    else
    {
    代码n
    }
    4、嵌套if-else语句
    If(表达式)
    {
    If(表达式)
    {
    代码
    }
    else
    {
    代码
    }
    }
    else
    {
    代码
    }
    五.函数
    1、一个源程序由多个函数组成。
    2、C程序的执行从main()函数开始;
    3、所有函数都是平行的;
    4、函数分类;可以分为标准和自定义,还可以分为有参函数和无参函数。
    函数定义的一般形式:
    1、类型标志符 函数名()
    {undefined
    声明部分
    语句
    }
    2、类型标志符 函数名(形式参数列表)
    {undefined
    声明部分
    语句
    }
    形参和实参的说明:
    (1) 在定义函数中指定的形参,在未出现函数调用时,他们并不占用内存中的存储单元,只有发生调用时,才会分配内存;
    (2) 实参可以是常量,变量或者表达式,有时传递的时地址;
    (3) 在被定义中,形参必须指定类型;
    (4) 实参与形参的类型应相同或赋值兼容;
    (5) C语言规定,实参变量对形参变量的数据传递是“值传递”,即单向传递,只有实参传递给形参,而不能由形参传递给实参。
    函数的返回值:
    希望通过函数调用使主调函数得到一个确定的值。
    1、函数的返回值是通过函数中的return语句获取的。
    2、函数值的类型;
    3、如果函数值的类型和return语句中表达式的值不一样,则以函数类型为准。
    4、如果调用函数中没有return语句,并不带回一个确定的用户需要的值,函数不是不带回值,而只是不带回有用的值,带回一个不确定的值。
    5、如不需要带回任何值,用void。
    函数的调用:
    调用方式:1、函数语句;2、函数表达式;3、函数参数。
    局部变量和全局变量:
    1、局部变量,在一个函数内部定义的变量称为内部变量,它只是在本函数范围内的有效,主函数也不能使用其它函数中定义的变量;不同函数中可以使用相同的名字的变量,他们代表不同的对象,互不干扰;形式参数也是局部变量;在一个函数内部,可以在复合语句中定义变量,这些变量只在本复合语句中有效,这种复合句也可以称为“分程序”或“程序块”;
    2、全局变量,在函数之外定义的变量称为外部变量,全局变量可以增加函数间数据联系的渠道,一般不再必要时不要使用,他在程序的全部执行过程中占用存储单元,是函数的通用性,使用全局变量会使程序的清晰性降低。还要注意若果同一源文件中,外部变量和局部变量同名,则在局部变量作用范围内,外部变量被“屏蔽”,不起任何作用。
    变量的存储类别:
    (变量值存储时间)动态存储方式,在程序运行期间进行分动态的分配存储空间的方式,静态存储方式是指在程序运行期间分配固定的存储空间的方式;存储空间分为程序区、静态存储区和动态存储区;全局变量全部放在静态存储区中,程序开始时分配空间,完毕时释放;动态存储区中存放以下数据:
    1、函数形式参数;
    2、自动变量;
    3、函数调用时的现场保护和返回地址;
    在C语言中每个变量和函数都有两个属性,是数据类型和数据存储类型,存储类别是数据在内存中存储的方式。
    存储方式分为静态和动态存储类,具体包含有四种:
    自动的(auto);
    静态的(static);
    寄存器的(register);
    外部的(extern),
    如果不加以声明,就自认为是auto型就会自动分配存储空间属于动态存储方式。
    static声明局部变量是在函数调用结束后不消失而保留原值,即占用存储单元不释放,在下一次调用该函数时,该变量已有值,就是上次函数调用结束时的值。其中需要说明的是在定义局部变量不赋初值的话,则静态局部变量编译时自动赋值为0或者空字符,虽然静态局部变量在函数调用结束后仍然存在,但是其他函数不能引用它的。静态局部变量主要用在当初始化后,变量只是被引用而不改变其值。
    register变量是C语言中允许将局部变量的值放在CPU中的寄存器中需要时直接从寄存器中取出来参加运算,不必再到内存中提取,但是计算机系统中寄存器数量有限,不能任意定义任意多的存储器,局部静态变量不能定义为寄存器变量。
    extern声明外部变量,用以扩展外部变量的作用域。在一个文件中,如果定义之前的函数想引用该外部变量,则应该在引用之前用关键字extern对该变量做外部变量声明。在多文件中,也可以采用extern声明的办法进行外部变量声明。
    有时希望某些局部变量只限于被本文件引用,而不能被其他文件引用,这时就可以采用在定义外部变量时外加一个static,这在程序模块化设计中加强了通用性。static来声明一个变量的作用有二个,一个是在声明对局部变量时。则为该变量分配的空间在整个程序执行期间始终存在;一个是在对全局变量声明中,该变量的作用域仅限于本文件模块操作。注意:这些方法同样适用于函数的声明。
    七.结构体,联合体(重要)
    结构体(struct)是一个或多个变量的集合,这些变量可能为不同的类型,为了处理的方便而将这些变量组织在一个名字之下。由于结构体将一组相关变量看作一个单元而不是各自独立的实体,因此结构体有助于组织复杂的数据,特别是在大型的程序中。

共用体(union),也称为联合体,是用于(在不同时刻)保存不同类型和长度的变量,它提供了一种方式,以在单块存储区中管理不同类型的数据。
结构体 / struct
结构体的定义
声明一个结构体类型的一般形式为:
struct 结构体名 {
成员列表
};
结构体变量(3种方式)

  1. 先声明结构体类型,再定义变量名
  2. 在声明类型的同时定义变量
    struct 结构体名 {
    成员列表
    } 变量名列表;
  3. 直接定义结构体类型变量其省略了结构体名
    struct {
    成员列表
    } 变量名列表;
    共用体
    union 共用体名 {
    成员列表
    } 变量

八.指针(重要)
指针是指向一片内存空间的地址,指针变量是变量,是存放一片内存空间首地址的变量,我们一般所说的指针都是指针变量。
指针的定义及赋值:
类型说明 *变量名  列如 int *p;
区别 int *p=NULL 与 *p=NULL
int p=NULL; //定义指针变量p,并且同时将p的值设置为0x00000000,不是把p的值设置为0x0000000,这个过程叫做初始化
int *p;p=NULL; //定义指针变量p,将p的值设置为NILL,即给p所指向的内存赋值NULL,但是p所指的内存可能是非法的,编译可能会显示内存访问错误,那么做出如下修改,给它一块合法的内存。
int i=10;int *p=&i;*p=NULL; //这时i中的值由10变成了0,而p值本身没变,即内存地址没有改变
指针的大小:
int *P;sizeof§; //指针的大小根据计算机的位数确定,32位机大小为4个字节,64位机大小为8个字节。
指针运算:
需要注意的是指针的类型,+1加的是一个指针类型的大小。
int a[10];int *p=&a; //+1,加了sizeof(int)*1个字节,而不是加sizeof(int[10])*1个字节
指针的使用类型
指针形式
数组形式:
int a[10];int *P=a;
p[0]=1; //指针的数组形式
*(p+1)=2; //指针的指针形式
通过指针修改内容的汇编过程
1.找到指针变量的地址
2.通过指针变量的地址,找到内容的地址
3.通过地址找到内容
4.修改内容
九.宏定义
1.基本使用
宏定义的基本语法:#define 宏名 宏体
#表示是预处理命令
define是宏命令
宏名:是符合C语言变量规则的名字,一般使用大写表示
宏体:“替换文本”可以是任意常数、表达式、字符串等
预处理会在程序进行编译之前进行处理,而宏便是在预处理的时候处理的,在后面程序中使用到宏时程序会一模一样的将宏体等效替换。
宏也分为带参宏和无参宏:
①带参宏:#define MIN(x,y) x<y?x:y
②无参宏:#define PI 3.1415926
宏定义的优点:
①方便程序修改,当我们在程序中需要多次使用某一个变量的时候,把他定义成一个宏便不用同时修改多处地方了。
②提高程序运行效率。宏定义是在预处理期间处理的,而函数是在编译期间处理的。这个区别带来的实质差异是:宏定义最终是在调用宏的地方把宏体原地展开,而函数是在调用函数处跳转到函数中去执行,执行完后再跳转回来。
注:宏定义和函数的最大差别就是:宏定义是原地展开,因此没有调用开销;而函数是跳转执行再返回,因此函数有比较大的调用开销。所以宏定义和函数相比,优势就是没有调用开销,没有传参开销,所以当函数体很短(尤其是只有一句话时)可以用宏定义来替代,这样效率高。

带参宏和带参函数的一个重要差别就是:宏定义不会检查参数的类型,返回值也不会附带类型;而函数有明确的参数类型和返回值类型。当我们调用函数时编译器会帮我们做参数的静态类型检查,如果编译器发现我们实际传参和参数声明不同时会报警告或错误。
注:用函数的时候程序员不太用操心类型不匹配因为编译器会检查,如果不匹配编译器会警告(但是实际测试并没有警告,理论上是有的);用宏的时候程序员必须很注意实际传参和宏所希望的参数类型一致,否则可能编译不报错但是运行有误(一般所希望的是整型数据类型,不然结果一般会出错。

缺点:
①由于是直接嵌入的,代码相对多一点。
②嵌套定义过多可能会影响程序的可读性,而且很容易出错,不容易调试。
③对带参的宏而言,由于是直接替换,并不会检查参数是否合法,存在安全隐患。

举报

相关推荐

0 条评论