(20220121)C语言(关键字、语句及运算)

目录

一、关键字

1、register

2、static

3、const

4、volatile

5、extern

6、struct(结构体)

     7、union(共用体)    

        return 0;}

8、enum

9、typedef

10、宏—#define

二、表达式及语句

        1、选择语句(if)

        2、循环语句(for  while  do ...while)

        3、switch分支语句

        4、goto语句

三、位运算

        1、按位与──&

        2、按位或──|

        3、按位异或──^

        4、按位取反──~

        5、按位左移──<<

         6、按位右移──>>

应用举例 [案例]

         [案例] 从键盘上输入1个正整数给int变量num,按二进制位输出该数。


一、关键字

1、register

        register:请求编译器尽可能地将变量存在CPU内部寄存器中;

        使用注意: register修饰变量的类型必须是CPU所接受的;

register变量可能不是在内存中存储,所以不能使用&来获取变量的地址(内存中含有地址)

2、static

        全局静态变量:作用范围局限于它的源文件,即只有本文件内的代码才可以访问它,变量名在其他文件内不可见

        局部静态变量:局限于特定函数,但出作用域并不释放,在函数体内的静态变量的值也能够维持

        静态函数:作用范围仅限于它的源文件,即只有本文件内才能够调用,函数名在其他文件不可见

存放位置(static):程序开始时,存放在全局数据区,程序结束时释放空间,默认初始化值是0,使用时可改变其值;

        局部变量 ——静态局部变量(由栈区 到 全局数据区;默认值由 垃圾值 到 0;作用范围特定函数内(不变));

        全局变量 ——静态全局变量(作用范围由 全部工程文件 到  当前文件;默认值为 0(不变);位置:全局数据区不变)

        普通函数 ——静态函数(作用范围由 全部工程文件  到  当前文件)

        函数不允许嵌套定义

        举例:认真体会:

        

3、const

        在面向对象语言当中(C++)中,const用于定义 常量;

        在C语言中,const用来定义只读变量

                strcpy( chsr *dest , const char *src) 指:源字符串(不可修改)复制到 (可改的目标文件中)

        const int* a; int const *a;    

        是一个指向const int型的指针,a所指向的内存单元不可改写,所以(*a)++是不允许的,但a可以改写,所以a++是允许的(若 int i;a = &i ; *a = 5(错误);所以不能通过*a 改变i 的值; 但是可以改变 i 的值;)

        int* const a;    

        a是一个指向int型的const指针,*a是可以改写的,但a不允许改写。

        int const * const a;    

        a是一个指向const int型的const指针,因此*a和a都不允许改写。

        const给读代码的人传达非常有用的信息。比如一个函数的参数是const char *,你在调用这个函数时就可以放心地传给它char *或const char *指针,而不必担心指针所指的内存单元被改写。         尽可能多地使用const限定符,把不该变的都声明成只读,这样可以依靠编译器检查程序中的Bug,防止意外改写数据

        const对编译器优化是一个有用的提示,编译器也许会把const变量优化成常量

4、volatile

        

         在寄存器定义(0x86);用volatile修饰,能较好的避免被优化掉;

5、extern

        extern:表明变量或函数的定义在别的文件中,下面用到的这些变量或是函数是外来的,不是本文件定义的,提示编译器遇到此变量或函数时,在其他模块中寻找定义;

        扩展使用范围:extern修饰变量的声明。举例来说,如果文件a.c需要引用b.c中变量int v,就可以在a.c中声明extern int v,然后就可以引用变量v。

        如下图所示:

        static 与 extern :static int a :静态全局变量 。如:下图所示:       

        

                 加上static,限制了a的作用域,在file2.c中引用失败;但不管是否加上static(不加是全局变量),a都按静态存储方式(全局数据区)存放。

        

        如果一个函数只能被本文件中其它函数所调用,称为内部函数(或静态函数)。定义时在函数类型前加static。(函数定义时,加与不加extern ,都是一样的)

6、struct(结构体)

        多种数据组合起来的一个整体,其表现形式是一个结构体。

        内存空间是分配给变量的,不分配给数据类型(不见变量,不分配)

        结构体变量的内存空间是由内部各个变量所占空间之和

        1、结构体创建(创建一个新的类型)

              方法一:

                struct node        

                {     char a;

                      short b;    

                      char c;

                 };                  (注意:;不能省)

                struct nade  link;(数据结构类型 定义变量(link))

                

                struct student

                {  int  num;    

                    char  name[20];    

                    float  score;

                 }stu1, stu2;  (等于:定义结构体类型 并且struct student  stu1,stu2;)

                

                方法二:

                typedef  struct 

                {     char a;

                      short b;    

                      char c;

                 }node;     

                 nade  link;(数据结构类型 定义变量(link))

                

                无名结构体定义:

                struct  {  int  num;    

                               char  name[20];    

                               float  score;

                            }stu1, stu2;(无名结构体类型  定义变量 stu1  ,stu2)

        2、结构体的意义

        结构体的花括弧内是该结构体中的各个成员,由它们组成一个结构体;在结构体内对各成员都应进行类型声明;                

        “成员表列”也称为域表。每个成员也称为结构体中的一个域,成员名命名规则与变量名一样;成员也可以是一个已定义的结构体类型变量:

 成员也可以是指向本结构体类型的指针变量(结构体指针只能指向自己):

        每个成员名前的类型标识符可以为已经定义了的任意类型,当然可以是结构体类型标识符,即结构体成员也可以是另一个结构体变量。     

        在程序中可以定义多个结构体类型,不同结构体类型用不同的结构体名来区分。

        3、结构体的引用形式

                结构体变量名. 成员名(“.”是成员运算符,在所有的运算符中优先级最高; ”.“一般变量用;—> 指向结构体的指针用)

        对结构体的操作就是对成员的一个个操作。而对结构体的整体操作只有两种情况:

        (初始化时,变量直接赋值; 两个同类型的结构体相互赋值)

                 结构体数组的赋值尤其要注意(strcpy(stu1.name, "Li Ming");)

                指向结构体变量指针的定义:

         注意:不能用指向结构体变量的指针指向该结构体变量的某个成员。

                

                 p是结构体类型,而stu.num属于 int  型(不匹配);

        4、访问结构体成员变量的三种方法:

                 说明:

                 “->”为指向运算符,是优先级最高的运算符

                 成员运算符“.”的优先级高于指针运算符“*”,因此采用 “(*p).成员名” 形式时,括号不能省略;

                注意以下几种运算:

        5、在定义结构体变量的同时,可以进行初始化

        注意:结构体变量的各个初值用花括号{、}括起来,大括号内各个成员变量的值之间用逗号分隔,其值必须与成员变量一一对应,且数据类型应与成员变量一致。

 

         6、结构体数组的初始化

        

          数组中各个元素的初值用大括号{、}括起来,同一数组元素的各个成员变量的初值用逗号分隔。stu[ ]:省略数组大小,必须提供所有的初始值;数组的定义(初始化下标大小;初始值数值;(必须有其中一个))。a[ ][ ],第一个方括号可以为空,第二个不行;a[ ][ ][ ]也是一样。

        7、字对齐与半字对齐

        字对齐:int型变量占四个字节,其他数据类型都按照四个字节的倍数分配(会产生内存空洞)。同类型的变量放在一起可以减少内存空洞

        后一个变量若能在前一个变量分配的空间中存放下,则后一个变量不再重新分配空间。

           半字对齐: short型变量占2个字节

         若即存在int 与 short 则 按照 int 的字节(字对齐);若 int 与 short 都不存在则按类型相加。

     7、union(共用体)    

       1、union的含义

        union(共用体) 使用方法与struct(结构体) 的使用方法相同

        当多个基本数据类型或复合数据结构要占用同一片内存时,我们要使用联合体(共用体)

        当多种类型,多个对象,多个事物只取其一时(我们姑且通俗地称其为“n 选1”),我们也可以使用联合体来发挥其长处;

                 

            2、大端字节序(网络字节序)

                 CPU是大端字节序还是小端字节序:通过公用体可以知晓(因为共用体的变量占同一段内存)

 试用共用体验证大小端字节序:

union node
{
        int a;
        char b;     (int a ; 与  char  b ; 占同一段旅内存空间。a 占四个字节;b 占一个字节;)
};                          (故通过 b 取出 a 的第一个字节,自然可以知道内存的存储顺序)                                   

int main()
{
        union node c;
        c.a =1;

        if(c.b == 1)
                printf("small!\n");               

        else
                printf("big!\n");

        return 0;
}

 

8、enum

        枚举类型声明代表常量的符号名称。

        enum的默认值    

        enum kids{nippy, slats, skippy, nina ,liz};

        enum kids a; a = nippy;

        enum的指定值    

        enum levels {low=100,medium=500,high=2000};

        enum levels a; a = low; (a = 100 (错误))a 不是整形 是枚举类型

        若枚举常量没有取值:默认:第一个为 0;后一个枚举常量是前一个值加1;

        enum的用法    

        作为switch的标签

9、typedef

        typedef是C语言的关键字,其作用是为一种数据类型定义一个新名字

        格式:typedef  数据类型  自定义数据类型

                typedef unsigned long uint32;

        在嵌入式的开发中,由于涉及到移植问题,typedef的功能就更引人注目了。

                如:

                typedef  struct 

                {     char a;

                      short b;    

                      char c;

                 }node;     

                 nade  link;(数据结构类型 定义变量(link))

int * ( * ( * fpl)( int ))[10]   (见:教你理解复杂的C-C++声明)

10、宏—#define

              1、带参数 

                定义常量与命令(避免幻数)

                #define  MAX 100    (MAX:宏名   100:宏体) 

                #define SIZE 1024         

                #define LOGIN_SUCCESS   1

                #define LOGIN_FAIL      0    

                注意:在宏定义的命名时,尽量能够清晰的表明其用途;

                预处理 == 宏展开  == 宏替换(字符替换;不做语法分析、不做运算)

               

               2、定义函数

                #define  MAX(a, b)  ((a)>(b)?(a):(b))

                                宏函数             宏体

                宏体 :所有形参 ,以及宏体都要加括号

                普通函数:做运算、做语法分析;

                宏函数:字符替换;不做语法分析、不做运算(多用于执行频率高且结构简单)

               

                #define语句:

                #define __DEBUG_

                #ifndef __DEBUG_

                #define debug_msg(fmt,args...)

                #else #define debug_msg(fmt, args...) printf(fmt,

                ##args)

                #endif

                #if  0/1

                ..........

                #endif    //用于注释代码是否执行

        

二、表达式及语句

        1、选择语句(if)

        if 语句是C 语言中最简单、最常用的语句,然而很多程序员用隐含错误的方式写if 语句

        本节以“与零值比较”为例,展开讨论

        布尔变量与零值比较

        整型变量与零值比较 

        浮点变量与零值比较  (用绝对值 :fads  做差,与1e-6比较)

        指针变量与零值比较 (与 null 相比较)

        2、循环语句(for  while  do ...while)

         for 语句使用频率最高,while 语句其次,do 语句很少用。

        重点论述循环体的效率。提高循环体效率的基本办法是降低循环体的复杂性。

        在多重循环中,如果有可能,应当将最长的循环放在最内层,最短的循环放在最外层,以减少CPU 跨切循环层的次数;

        a与b交换(三种):

                a = a+b; b = a -b; a = a - b;

                a = a^b; b = a^b; a = a^b;

                t = a ; a = b; b = t;

        3、switch分支语句

                 switch语句可以产生具有多个分支的控制流程。    

                它的格式是:      

                switch(控制表达式)      

                {          

                        case常量表达式:语句列表 ;break          

                        case常量表达式:语句列表  ;  break        

                                 ...                 

                        default:语句列表      ;  break;

                }

               每个case 语句的结尾不要忘了加break,否则将导致多个分支重叠(除非有意使多个分支重叠);

                不要忘记最后那个default 分支。即使程序真的不需要default 处理,也应该保留语句 default : break; 这样做并非多此一举,而是为了防止别人误以为你忘了default 处理。

        4、goto语句

        自从提倡结构化设计以来,goto 就成了有争议的语句。首先,由于goto 语句可以灵活跳转,如果不加限制,它的确会破坏结构化设计风格。其次,goto 语句经常带来错误或隐患。它可能跳过了某些对象的构造、变量的初始化、重要的计算等语句,例如:      

        goto state;       char s1, s2; // 被goto 跳过      

        int sum = 0; // 被goto 跳过      

        state:    

        如果编译器不能发觉此类错误,每用一次goto 语句     都可能留下隐患。

        goto只用于跳出多循环

三、位运算

        1、按位与──&

        

         主要用途:清0(写0),保留某些位(写1)

        2、按位或──|

        

         主要用途:置1(写1),保留某些位(写0)

        3、按位异或──^

        

          主要用途:使1个数的某(些)位翻转(即原来为1的位变为0,为0的变为1),其余各位不变。

        4、按位取反──~

        

          主要用途:间接地构造一个数,以增强程序的可移植性。

        5、按位左移──<<

        

         6、按位右移──>>

                

         说明:

        (1)x、y和“位数”等操作数,都只能是整型或字符型数据。除按位取反为单目运算符外,其余均为双目运算符。

        (2)参与运算时,操作数x和y,都必须首先转换成二进制形式,然后再执行相应的按位运算。 例如,5<<2=20:0101 → 10100,20 >> 2=5:10100 → 00101

        (3)实现&、|、^运算主要用途的方法  

          1)构造1个整数:该数在要取(或保留)的位、或要置1的位、或要翻转的位上为1,其余均为0。

          2)进行按位与、或按位或、或按位异或操作。

        (4)实现按位取反主要用途的方法  

          1)求~0,间接地构造一个全1的数;  

          2)按需要进行左移或右移操作,构造出所需要的数。 例如,直接构造一个全1的数,在IBM-PC机中为0xffff(2字节),而在VAX-11/780上,却是0xffffffff(4字节)。如果用~0来构造,系统可以自动适应。

        

应用举例 [案例]

从键盘上输入1个正整数给int变量num,输出由8~11位构成的数(从低位、0号开始编号)。

         程序说明:~ ( ~0 << 4)    

        按位取0的反,为全1;左移4位后,其低4位为0,其余各位为1;再按位取反,则其低4位为1,其余各位为0。这个整数正是我们所需要的。

         [案例] 从键盘上输入1个正整数给int变量num,按二进制位输出该数。

        

        1.复合赋值运算符 除按位取反运算外,其余5个位运算符均可与赋值运算符一起,构成复合赋值运算符: &=、|+、^=、<<=、>>=  

        2.不同长度数据间的位运算──低字节对齐,短数的高字节按最高位补位:

        (1)对无符号数和有符号中的正数,补0;

        (2)有符号数中的负数,补1。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值