精华内容
下载资源
问答
  • 该资源是c语言重要知识点总结,基于谭浩强著c语言程序设计一书。
  • c语言重要知识点总结

    2018-08-28 19:03:53
    总结 3.3 内存对齐 Char 偏移量必须为sizeof(char)即1的倍数 int 偏移量必须为sizeof(int)即4的倍数 float 偏移量必须为sizeof(float)即4的倍数 double 偏移量必须为sizeof(double)即8的倍数 Short ...

    1 关键字

    1.1 sizeof

    sizeof是关键字,不是函数

    1.2 static

    static两个作用:限制作用域(本文件),延长生命周期

    • 静态全局变量:作用域仅限于变量被定义的文件中,其他文件即使用extern声明也没法使用他。
    • 静态局部变量:由于被static修饰的变量总是存在内存的静态区,所以即使这个函数运行结束,这个静态变量的值还是不会被销毁,函数下次使用时仍然能用到这个值

    静态函数:作用域仅限于本文件

    1.3 基本数据类型

    float 4byte, double 8byte

    1.4 变量命名规则
    • 所有宏定义、枚举常数、只读变量全用大写字母命名,用下划线分割单词
    • 定义变量的同时千万千万别忘了初始化。定义变量时编译器并不一定清空了这块内存,它的值可能是无效的数据
    1.5 signed

    编译器缺省默认情况下数据为 signed 类型

    1.6 switch case

    case后面只能是整型或字符型的常量或常量表达式(想想字符型数据在内存里是怎么存的)

    1.7 if else

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

    1.8 void

    void*指针,任何类型的指针都可以直接赋值给它,无需进行强制类型转换,“空类型”包含“有类型”

    1.9 const
    • const修饰的只读变量必须在定义的同时初始化
    • 先忽略类型名(编译器解析的时候也是忽略类型名),我们看const离哪个近。“近水楼台先得月”,离谁近就修饰谁。
      const int *p; // const 修饰*p, p是指针,*p是指针指向的对象,不可变
      int const *p; //const 修饰*p,p 是指针, *p 是指针指向的对象,不可变
      int *const p; /const 修饰 p, p 不可变, p 指向的对象可变
      const int *const p; //前一个 const 修饰“, 后一个 const 修饰 p,指针 p 和 p 指向的对象都不可变
    1.10 union

    在 union中所有的数据成员共用一个空间,同一时间只能储存其中一个数据成员,所有的数据成员具有相同的起始地址

    2 符号

    • 逻辑运算符||的条件只要有一个为真,其结果就为真;只要有一个结果为假,其结果就为假
    • 左移和右移:当为正数时, 最高位补 0;而为负数时,符号位为 1,最高位是补 0 或是补 1 取决于编译系统的规定。 Tu rbo C 和很多系统规定为补 1
    • 左移和右移的位数不能大于数据长度,不能小于0
    • “ +”号的优先级比移位运算符的优先级高
    2.1 运算优先级

    1 []高于*,比如int *a[];
    2 函数()高于*,比如 int *fp();
    3 ==和!=高于位运算,比如val & mask != 0;
    4 ==和!=高于赋值运算符,比如c = getchar() != EOF
    5 算术运算符高于赋值运算符,比如 msb << 4 + lsb

    3 预处理

    另外 ANS I 标准 C 还定义了如下几个宏:
    _LINE_ 表示正在编译的文件的行号
    _FILE_ 表示正在编译的文件的名字
    _DATE_ 表示编译时刻的日期字符串,例如: “25 Dec 2007 ”
    _TIME_ 表示编译时刻的时间字符串,例如: “12:30:55”
    _STDC_ 判断该文件是不是定义成标准 C 程序

    3.1 宏定义

    反斜杠作为接续符时,在本行其后面不能再有任何字符,空格都不行
    宏的生命周期从#define开始到#undef结束
    #include <filename> 先到规定系统路径去寻找 include "filename" 先到当前目录去寻找

    3.2 #pragma

    待总结

    3.3 内存对齐

    Char 偏移量必须为sizeof(char)即1的倍数
    int 偏移量必须为sizeof(int)即4的倍数
    float 偏移量必须为sizeof(float)即4的倍数
    double 偏移量必须为sizeof(double)即8的倍数
    Short 偏移量必须为sizeof(short)即2的倍数
    例:下面这个结构体中sizeof(MyStruct)为8+4+4=16

    struct MyStruct 
    { 
    double dda1; 
    char dda; 
    int type 
    }; 

    可以好好摆放结构体中元素的位置以充分利用内存
    使用指令#pragma pack(n),编译器将按照 n 个字节对齐,对于特定item,对其的基准为min(n,sizeof(item))
    使用指令#pragma pack(),编译器将取消自定义字节对齐方式。

    3.4 #运算符
    #define SQR(x) printf("The square of x is %d.\n,((x)*(x))");

    运行SQR(8)输出 The square of x is 64

    #define SQR(x) printf("The square of #x is %d.\n,((x)*(x))");

    运行SQR(8)输出 The square of 8 is 64

    3.5 ##运算符
    #define XNAME(n) x##n

    XNAME()会被展开成x8.##就是个粘合剂,将前后两部分粘合起来

    4 指针和数组

    4.1 野指针
    int *p;
    *p = NULL;

    注意,NULL定义#define NULL 0,但是NULL和0表示的意思完全不一样

    4.2 省政府与市政府区别

    注意sizeof(a)=sizeof(int)*5,因为a代表的是数组的整块内存
    &a是数组首地址(省政府),&a[0]是数组首元素首地址(市政府)

    4.3 数组名作为左值和右值的区别

    对于x=y,左值:x代表的地址,右值:y所代表的地址里面的内容
    对于数组,int a[5]
    - a**作为右值,代表数组首元素的首地址**,所以才可以用a[i]访问数组内的元素。
    - a**不能做左值!!!**

    4.4 a和&a的区别

    &a是数组a的首地址a地址一样,但是意思不一样

    int a[5] = …;  //省略具体数值
    *(a+1)  //a是数组首元素的首地址,所以+1之后是下一个元素的地址
     &a+1  //指向的是下一个数组 &a+5*sizeof(int),即`a[5]`,已经越界
    int *ptr = (int *)(&a+1) // 将上一步计算出来的地址强制转换成int*类型
    *(ptr-1)  //指向`a[4]`
    4.4 指针数组和数组指针
    • 指针数组:存储指针的数组,int* p[10]
    • 数组指针:指向数组的指针,int (*p)[10]
    4.5 地址强制转换
    struct Test{
    ...
    }*p;

    假设p的值是0x100000,那么

    p + 0x1 = 0x100000 + sizeof(Test)  //与数组的指针变量加减整数一样,整数的单位是元素的个数
    (unsigned long)p + 0x1 = 0x100001   //整数与整数相加
    (unsigned int*)p + 0x1 = 0x100004    //0x100000 + (unsigned int)*0x1
    int a[4] = {...};
    int *ptr = (int*)((int)a+1);  //元素a[0]的第二个字节开始的连续4byte的地址
    4.6 二维指针
    int a[5][5];
    int (*p)[4];
    p=a;

    分析一下p[4][2]: &p[0]+4*4*sizeof(int)+2*sizeof(int)

    4,7 数组参数与指针参数
    • 一维数组作为函数参数的时候,编译器总是把它解析下好呢给一个指向其首元素首地址的指针
    • main函数内的变量不是全局变量,而是局部变量,只不过它的生命周期和全局变量一样长。全局变量一定是在函数外部定义的。
    • 指针作为参数的时候,同样传递的是拷贝的那份,并不是指针本身
    void getmemory(char *p, int num){
        p = (char*)malloc(sizeof(char)*num);
    }
    int main(){
        char * str = NULL;
        getmemory(str,10);
    }

    上面的程序中malloc的内存的地址并没有复制给str,而是给了_str。解决办法:
    (1)用return

    void getmemory(char *p, int num){
        p = (char*)malloc(sizeof(char)*num);
        return p;
    }
    int main(){
        char * str = NULL;
        str = getmemory(str,10);
    }

    (2)二级指针:因为要操作的是指针,所以传入指针的地址,即二级指针

    void getmemory(char **p, int num){
        *p = (char*)malloc(sizeof(char)*num);
    }
    int main(){
        char * str = NULL;
        getmemory(&str,10);
    }
    4.8 函数指针
    char* fun(char* p1,char* p2){
    ……
    }
    void main(){
        char *(*pf)(char* p1,char* p2);
        pf = &fun;或者 pf = fun; //函数名被编译之后其实就是一个地址,所以两种方法没有本质区别
        (*pf)("aa","bb");
    }
    void func(){
    ...
    }
    void main(){
        void (*p)();
       *(int*)&p = (int)func;  //将函数的入口地址赋值给指针变量
       //(int*)&p将地址强制转换成指向int类型数据的指针
       //(int)func将函数的入口地址强制转换成int类型数据
       //*(int*)&加锁,转向,解锁
    }
    char* (*pf[3])(char *p); //函数指针数组,数组名是pf
    char*  (*(*_pf)[3])(char *p); //函数指针数组的指针,_pf是指针,相当于用(*_pf)替换pf

    5 内存管理

    5.1 野指针

    指针变量除了在使用时,别的时间都把针拴到“0”地址处,即

    • 定义指针变量的同时最好初始化为NULL
    • 用完指针之后也将指针变量设置为NULL
    5.2 结构体指针未初始化
    struct student{
        char* name;   //只分配了四个字节,name并没有指向一个合法的地址,这时候其内部存的只是一些乱码
        ...
    }stu;
    void main(){
        strcpy(stu.name,"Jimy");
        ...
    }

    解决方法:为name malloc一块内存空间

    5.3 数组内存的初始化
    int a[10]={0};
    memset(a,0,sizeof(a));
    5.4 malloc函数

    原型(void *)malloc(int size),由于返回值是void *,所以需要进行强制转化,比如

    char *p = (char*)malloc(100);

    使用malloc函数需要注意,如果所申请的内存块大于目前堆上剩余的整块内存块,则内存分配失败,函数返回NULL。注意,这里说的“剩余的整块内存块”不是所有剩余内存块之和,因为malloc函数申请的是连续的一块内存。所以,malloc函数必须用if(NULL != p)来验证内存分配是否成功。

    展开全文
  • C语言重要知识点总结(一)

    千次阅读 2015-10-15 20:04:38
    C语言重要知识点总结(一)最近重新看了下C语言,发现先前学习的时候很多的重点都被忽略了,现在回头看发现了很多以前没有注意的东西,所以写博客记录下,方便以后可以参考查询。 变量的存储类别C语言中变量的存储...

    C语言重要知识点总结(一)

    最近重新看了下C语言,发现先前学习的时候很多的重点都被忽略了,现在回头看发现了很多以前没有注意的东西,所以写博客记录下,方便以后可以参考查询。

    1. 变量的存储类别

      C语言中变量的存储类别有auto,register,extern和static。下面将对以下四个存储类别进行详细的介绍:
      auto:自动变量,默认的存储类型,根据变量定义的位置决定变量的生命周期和作用域。如果定义在任何一个函数的外面则编译器将改变量定为全局变量。如果定义在函数里面,则编译器则会将改变量识别为局部变量。
      register:寄存器变量,这个类别的变量会被优先分配到寄存器。通常作为循环因子的变量会被分配到寄存器。
      extern:外部变量(全局变量),该关键字用来扩展全局变量的作用域。扩展的范围是从使用extern变量开始到改文件结尾。extern关键字所做的工作只是让其他文件中的程序可以引用该变量,并不会改变这个变量的生命周期。extern修饰的一定是全局变量,修饰局部变量没有意义。
      static静态变量,以前以为用static修饰的变量是存放在堆中的,现在觉得不是。static是用于限制作用域的,被static修饰的变量存储在数据段中,无论static修饰的是全局变量还是局部变量都是被存放在数据段中的。被static修饰的变量可以细分为static全局变量和static局部变量。下面对分别对static全局变量和static局部变量从作用域和生命周期进行总结:

      staitc变量 作用域 生命周期
      staitc全局变量 只作用于本文件,也就是说只有本文件的函数可以引用改全局变量。 在整个程序执行过程中该变量一直存在。
      staitc局部变量 作用域和普通的局部变量一样,只能作用在其所定义的复合语句中,也就是其他函数不可访问。 在整个程序执行过程中该变量一直存在,因为不是存放在栈中而是存放在数据段内。

      正是被static修饰的变量有如上的特性,所以static变量在C语言中有一个很显著的作用就是可以实现一个模块的封装。在C语言中一个源程序文件就是一个模块,由于被static声明的全局变量只能被本文件的函数访问,所以当用户在一个文件中定义一个static全局变量后,其他文件(模块)只能通过该模块提供的接口函数来访问这个static变量,而不能直接对其进行操作。

      2. 数组指针和指针数组
      这两个概念是我自己总结,其实自己也有点迷糊。数组指针是指数组的指针,而指针数组是指指针的数组。
      指针数组:指针的数组好理解,就是存放指针的数组,在C语言中定义如下:

            int *p[10];

    该定义指定了一个存放10个指向int的指针的数组。
    数组指针:数组的指针,顾名思义,就是指指向一个数组的指针。在C语言中的定义如

            int (*p)[10];

    一个指针,指向一个数组对象,该数组是一个拥有10个整型元素的数组。
    注意:当执行P+1是,p移动的字节数不是int的字节数,而是整个数组的字节数。如上面的定义,当执行p+1时,移动的是sizeof(int)*10=40个字节。
    3. 内存对齐
    为了高速的处理数据,现代处理器的设计引入了对齐的概念。所谓对齐就是保证数据在内存中的存储时地址变化按照一定的规律,主要目的是保证CPU每次都可以取同样长度的数据进行运算,因此可以提高计算机运行的速度。是一种用空间换时间的策略。

    struct test1{
        char ch;
        short s;
        int i;
    }

    在32位体系结构中定义如上的结构体。用sizeof()测试上面结构体的大小的结果是8字节

    struct test2{
        char ch;
        int i;
        short s;
    }

    在32位体系结构中定义如上的结构体。用sizeof()测试上面结构体的大小的结果是12字节
    出现上面的现象就是由于内存对齐。在32位体系结构中默认采用4字节的对齐方式。也就是说CPU一次读取字节的大小为4个字节。当只有一个字符变量的时候,第一个字节存储字符变量的值,剩下的3个用空白值填充。当对于结构体test1中的情况是将字符型变量ch和短整型变量存储在一个4字节的内存区域,多出的一个字节用无用值填充。所以测试的结果是8字节。用图形表示如下:
    test1 内存对齐图test2 内存对齐图

    展开全文
  • 及详解) 最后推荐文章: C语言重要知识点总结【4】:C语言的32个关键字和9种控制语句 C语言重要知识点总结【7】:C语言中的常量、变量、标识符 C语言重要知识点总结【8】:C语言中变量的数据类型 C语言重要知识点...

    大一下学期学习了C语言、暑假在家没事又把C语言复习了一遍。因此,趁热打铁,把所学内容写成笔记,以便以后复习,也希望能够帮助大家学好C语言。
    以下内容如有错误,请大家在评论区指正,谢谢支持,共同进步。 go、go、go !!!

    一、控制语句及其用处(表格)

    控制语句,用于完成一定的控制功能。C语言 只有 9种控制语句,它们的形式是:

    共9个 表现形式 用处
    1 if()···或 if()···else··· 条件语句
    2 for()··· 循环语句
    3 while()··· 循环语句
    4 do···while() 循环语句
    5 continue 结束本次循环语句
    6 break 中止执行 switch 或 循环语句
    7 switch 多分支选择语句
    8 return 从函数返回语句
    9 goto 转向语句,在结构化的程序中基本不用goto语句

    在上边的9种语句表示形式中:

    () 表示括号中是一个“判别条件
    ··· 表示 内嵌的语句

    二、控制语句详细表示(图片)

    下面这张图片是《C程序设计》书附录中的一个片段,我个人感觉这张图片对9种控制语句概括的内容写得也很不错。

    算是上边内容的一个补充吧:上边表格中的“判别条件”实际就是由表达式构成

    在这里插入图片描述

    三、9种控制语句(详解)

    1. if()···else··· 语句

    if(a>b)
        max=a;
    else
        max=b;

    x>y判别条件
    max=a;max=b;是语句,这两个语句内嵌在if···else语句中,这个if···else语句的作用是:先判别条件a>b是否成立,如果a>b成立,就执行内嵌语句max=a;,否则就执行内嵌语句max=b;

    选择结构中条件语句一共有3种形式:

    ①第一种:

    if(表达式)  语句1 (没有else部分)

    ②第二种:

    if(表达式1)
        语句1
    else
        语句2    
    

    ③第三种:

    if(表达式)  语句1
    else if(表达式)  语句2
    else if(表达式)  语句3
    ······
    else  语句 n

    2. break语句 和 continue语句

    在介绍break语句 和 continue语句在程序中作用之前我们先看一下下面3个简单的程序,我会在最后用图片总结出 break语句 和 continue语句的区别:

    题目:输出以下4X5矩阵
    在这里插入图片描述
    程序:…………………………………………

    #include<stdio.h>
    int main()
    {
        int i,j,n=0;
        for(i=1;i<=4;i++)
        {
            for(j=1;j<=5;j++)
            {
                printf("%d\t",i*j);
                n=n+1;
                if(n%5==0)
                    printf("\n");
            }  
            printf("\n");
        }
        return 0;
    }

    运行结果:…………………………………………
    在这里插入图片描述

    程序:…………………………………………

    break语句在程序中的应用:

    #include<stdio.h>
    int main()
    {
        int i,j,n=0;
        for(i=1;i<=4;i++)
        {
            for(j=1;j<=5;j++,n++)
            {
                if(n%5==0)
                    printf("\n");
                if(i==3 && j==1) break;
                    printf("%d\t",i*j);      
            }  
        }
        printf("\n");
        return 0;
    }

    运行结果:…………………………………………
    在这里插入图片描述
    continue语句在程序中的应用:

    程序:…………………………………………

    #include<stdio.h>
    int main()
    {
        int i,j,n=0;
        for(i=1;i<=4;i++)
        {
            for(j=1;j<=5;j++,n++)
            {
                if(n%5==0)
                    printf("\n");
                if(i==3 && j==1) continue;
                    printf("%d\t",i*j);      
            }  
        }
        printf("\n");
        return 0;
    }

    运行结果:…………………………………………

    在这里插入图片描述

    break语句 和 continue语句对比

    图中两个程序中的代码就红方框中不一样,其它代码完全相同,那么我们从中可以得到什么结论:

    在这里插入图片描述

    从上图的对比情况,可以很容易看出:

    break 直接跳出 i=3(1<= j <=5)的 整个循环
    continue 是只循环结束 j=1(i=3) 本次循环

    continue 和 break语句在循环结构 for、while、do···while() 语句中用的都比较多。

    但,continue语句一般只用于循环语句中;而break语句 不仅可以在循环语句中可以使用,在switch语句中也会经常使用到,在switch语句中的运用在后面对switch 语句百分制成绩中介绍。

    3. switch 语句

    switch语句的一般形式如下:

    switch(表达式)
    {
        case 常量表达式1 : 语句1
        case 常量表达式2 : 语句2
        ···
        case 常量表达式n : 语句n
        default :  语句n+1
    }

    前缀case 和 default 本身并不改变控制流程,它们之起标号作用,在执行上一个case后标志的语句后,继续顺序执行下一个case 前缀所标志的语句,除非上一个语句中最后用break语句是控制转出switch结构。

    注意:
    ①根据程序要求 default 可要可不要
    ②case 后面的常量必须互不相同

    下面我们看一个switch实例:

    switch 语句(内含break语句)

    题目:要求按照考试成绩的等级输出百分制分数段,A等为85分以上,B等为70 ~ 84分,C等为60 ~ 69,D等为60分以下。成绩等级由键盘输入。

    switch语句:多分支选择语句

    #include<stdio.h>
    int main()
    {
        char grade;
        printf("输入等级:");
        scanf("%c",&grade);
        printf("成绩范围:");    //输入大写字母:A B C D 
        switch(grade)
        {            
            case 'A':printf("85~100");break;
            case 'B':printf("70~84");break;
            case 'C':printf("60~69");break;
            case 'D':printf("<60\n");break;
            default: printf("enter data error!\n");break;   //输入数据不在范围内 
        }
        return 0;
    }

    执行结果…………………………

    在这里插入图片描述

    其它文章

    1. c语言百分制成绩转换的2种方法(switch语句或if语句)
    2. 判断闰年的3种方法(判断+范围输出)

    4. while 语句

    while语句的一般形式如下:

    while(表达式)  语句

    下面举一个简单的例子:

    问题:求1+2+3+…+100

    程序:………………………………

    #include<stdio.h>
    int main()
    {
        int i=1,s=0;
        while(i<=100)
        {
            s=s+i;   //累加求和
            i++;
        }
        printf("s=%d\n",s,i);
        return 0;
    }

    执行结果…………………………

    在这里插入图片描述

    5. do()···while 语句

    do()···while语句的一般形式:

    do
        语句
    while(表达式);

    【注意】while(表达式)后面要以 ; 结尾

    问题:求1+2+3+…+100

    程序:……………………………………

    #include<stdio.h>
    int main()
    {
        int i=1,s=0;
        do
        {
            s=s+i;  //累加求和
            i++;
        }
        while(i<=100);
        printf("s=%d\n",s,i);
        return 0;
    }

    执行结果…………………………………

    在这里插入图片描述

    6. for 语句

    for语句的一般形式为:

    for(表达式1;表达式2;表达式3) 
        语句

    问题:求1+2+3+…+100

    程序:………………………………

    #include<stdio.h>
    int main()
    {
        int i,sum=0;                       
        for(i=1;i<=100;i++)
            sum+=i;    //累加求和
        printf("sum=%d\n",sum);
        return 0;
    }

    执行结果:………………………………
    在这里插入图片描述

    7. for、while、do···while() 语句对比

    for语句与while语句对比

    3种循环都可以用来处理同一问题,一般情况下他们可以相互代替。而for语句在有关循环的问题中是最常用的,for语句更为灵活,不仅可以用于 循环次数已确定 的情况,还可以用于循环次数不确定而只给出循环条件的情况,它完全可以代替while语句

    for(表达式1;表达式2;表达式3) 
        语句
    表达式1while(表达式2)
    {
        语句
        表达式3}

    while语句与do···while()语句对比

    do···while()语句的执行过程:先执行一次循环体,然后再检查条件是否成立,若成立,在执行循环体。do···while()语句至少要执行一次循环体

    while语句:先判断条件是否成立,若成立再执行循环体。

    for、while、do···while() 三种循环语句可以处理很多复杂的问题,我们就不一一介绍了,如果你感觉对于上面的循环内容还没有看够,可以看一下下面几个关于循环的几个算法实例

    1. 素数(判断,统计,范围输出)
    2. 完数 (判断、范围输出)
    3. 水仙花数(输出全部水仙花数)

    8. goto 语句

    goto:转向语句,在结构化的程序中基本不用goto语句,在这里就不作介绍了。

    9. return 语句

    return:从函数返回语句

    几乎我们写的每一个程序一般都要使用return语句,作用就是从函数返回语句。一个函数可以有一个以上的 return语句 ,执行到那个return语句,哪一个return语句起作用。return后面的括号可以不要:

    return z;return(z); 等价

    return 0;
    return z;
    return(z);

    函数的返回值是通过函数中的return语句获得的:

    主函数main的返回值为 0 时表示程序正常退出
    返回值为非零时,表示程序异常退出

    最简单的程序(Hello world!及详解)

    最后推荐文章:

    相见就是【猿分】
    在这里插入图片描述

    以上内容如有错误,请大家在评论区指正,谢谢支持,共同进步。 加油!!!
    如果你感觉我写的内容对你有一定的帮助,请给我点一个 【赞】作为您对我的鼓励, 谢谢!!

    在这里插入图片描述

    展开全文
  • C语言重要知识点总结【9】:C语言运算符(详解)

    多人点赞 热门讨论 2020-10-12 17:52:21
    C语言把括号、逗号、叹号、赋值和强制转换等都作为运算符处理,从而使C语言的运算类型及其丰富,表达式类型多样化。灵活使用运算符可以实现在其他高级语言中难以实现的运算。 基础的C语言运算符是每个程序员都应该...

    一、前言

    C语言主要特点之一:运算符丰富

    C语言的运算符包含的范围广泛,共有34种运算符。C语言把括号、逗号、叹号、赋值和强制转换等都作为运算符处理,从而使C语言的运算类型及其丰富,表达式类型多样化。灵活使用运算符可以实现在其他高级语言中难以实现的运算。

    基础的C语言运算符是每个程序员都应该学会的,我们非常有必要清晰地知道运算符一共有哪些哪些是需要我们必须掌握的。

    这篇文章对C语言常见运算符进行详细讲解,由于在学校写博客的时间少和不方便,所以部分内容我会用我以前用office制作的PPT截图进行分析。
    如果文章中有啥错误和分析不到位的地方,希望大家指点 ,谢谢支持,共同进步!!!

    二、运算符分类

    共12类 运算符种类 运算符
    1 算术运算符 + - * / % ++ --
    2 关系运算符 > < == >= <= !=
    3 逻辑运算符 ! && ||
    4 位运算符 << >> ~ | ^ &
    5 赋值运算符 =(及其扩展赋值运算符)
    6 条件运算符 ? :
    7 逗号运算符 ,
    8 指针运算符 *&
    9 求字节运算符 sizeof
    10 强制类型转换运算符 类型
    11 成员运算符 .->
    12 下标运算符 [ ]
    13 其它 如函数调用运算符()

    【注意】可从一下几个角度大致可将C语言的运算符分为:13类运算符 或 34种运算符,总共有44个运算符。

    细心的你会发现上面运算符不够44个,对于第5类运算符:赋值运算符一共有11个。在下面运算符优先级和结合方向表格中会详细介绍。

    三、运算符的优先级

    运算符的优先级一共可分为15级:

    1级优先级最高15级优先级最低

    同一优先级的运算符(当一个运算对象两侧运算符的优先级别相同时),运算次序由结合方向(结合性)所决定, 除了单目运算符三目运算符赋值运算符这三种是从右往左外,其他的运算符都是从左往右

    常用运算符常见记法:

    > 算术运算符 > 关系运算符 > && > || > 赋值运算符

    优先级 运算符 含义 结合方向 对象个数
    1 ( ) 圆括号 自左至右
    1 [ ] 下标运算符 自左至右
    1 -> 指向结构体成员运算符 自左至右
    1 . 结构体成员运算符 自左至右
    2 ! 逻辑非运算符 自右至左 1(单目运算符)
    2 ~ 按位取反运算符 自右至左 1(单目运算符)
    2 ++ 自增运算符 自右至左 1(单目运算符)
    2 - - 自减运算符 自右至左 1(单目运算符)
    2 - 负号运算符 自右至左 1(单目运算符)
    2 (类型) 类型转换运算符 自右至左 1(单目运算符)
    2 * 指针运算符 自右至左 1(单目运算符)
    2 & 取地址运算符 自右至左 1(单目运算符)
    2 sizeof 长度运算符 自右至左 1(单目运算符)
    3 * 乘法运算符 自左至右 2(双目运算符)
    3 / 除法运算符 自左至右 2(双目运算符)
    3 % 求余运算符 自左至右 2(双目运算符)
    4 + 加法运算符 自左至右 2(双目运算符)
    4 - 减法运算符 自左至右 2(双目运算符)
    5 << 左移运算符 自左至右 2(双目运算符)
    5 >> 右移运算符 自左至右 2(双目运算符)
    6 > 大于运算符 自左至右 2(双目运算符)
    6 >= 大于等于运算符 自左至右 2(双目运算符)
    6 < 小于运算符 自左至右 2(双目运算符)
    6 <= 小于等于运算符 自左至右 2(双目运算符)
    7 == 等于运算符 自左至右 2(双目运算符)
    7 != 不等于运算符 自左至右 2(双目运算符)
    8 & 按位异或运算符 自左至右 2(双目运算符)
    9 ^ 按位与运算符 自左至右 2(双目运算符)
    10 | 按位或运算符 自左至右 2(双目运算符)
    11 && 逻辑与运算符 自左至右 2(双目运算符)
    12 || 逻辑或运算符 自左至右 2(双目运算符)
    13 ? : 条件运算符 自右至左 3三目运算符
    14 = 赋值运算符 自右至左 2(双目运算符)
    14 += 加后赋值 自右至左 2(双目运算符)
    14 -= 减后赋值 自右至左 2(双目运算符)
    14 *= 乘后赋值 自右至左 2(双目运算符)
    14 /= 除后赋值 自右至左 2(双目运算符)
    14 %= 去取后赋值 自右至左 2(双目运算符)
    14 >>= 左移后赋值 自右至左 2(双目运算符)
    14 <<= 右移后赋值 自右至左 2(双目运算符)
    14 &= 按位与后赋值 自右至左 2(双目运算符)
    14 ^= 按位异或后赋值 自右至左 2(双目运算符)
    14 |= 按位或后赋值 自右至左 2(双目运算符)
    15 , 逗号运算符 自左至右

    四、常用运算符

    通过上面介绍的内容,接下来开始介绍常见运算符的使用。

    1. 算术运算符

    运算符与含义 对象个数 结合方向 优先级
    ++(自增) 1 单目运算符 2
    - - (自减) 1 单目运算符 2

    在这里插入图片描述

    在这里插入图片描述

    2. 关系运算符

    运算符与含义 对象个数 结合方向 优先级
    < (小于) 2 双目运算符 左 → 右 6
    <= (小于等于) 2 双目运算符 左 → 右 6
    > (大于) 2 双目运算符 左 → 右 6
    >= (大于等于) 2 双目运算符 左 → 右 6
    == (等于) 2 双目运算符 左 → 右 7
    != (不等于) 2 双目运算符 左 → 右 7

    关系运算符常用在条件判断,循环结构等中:

    for(i=0; i<10; i++)
    if(a < b+c)
    if(a != 0) //等同 if(a)
    
    

    在这里插入图片描述

    #include <stdio.h>
    int main()
    {
        int a=3,b=5,c=1;
        printf("b>a = 5>3      结果:%d\n",b>a);
        printf("b>a>c = 5>3>1  结果:%d\n",b>a>c);
        printf("b>=a = 5>=3    结果:%d\n",b>=a);
        printf("b!=a = 5!=3    结果:%d\n",b!=a);
     
     return 0;
    }
    

    在这里插入图片描述

    3. 逻辑运算符

    运算符与含义 对象个数 结合方向 优先级
    ! (逻辑非) 1 单目运算符 2
    && (逻辑或) 2 双目运算符 左 → 右 11
    ||(逻辑与) 2 双目运算符 左 → 右 12

    优先级:! > && > ||

    if((year%4==0 && year%100!=0) || (year%400==0))
         printf("%d是闰年\n",year);
    

    判断闰年的3种方法(判断+范围输出)

    在这里插入图片描述

    4. 赋值运算符

    赋值运算符共有11个:

    • 结合性:从右到左,优先级14
    • 双目(元)运算符
    • 赋值运算符: " = "
    • 复合的赋值运算符(扩展赋值运算符): +=-=*=/=%=>>=<<=&=|=^=
    1. 赋值运算符: =
    变量 = 常数;
    a = 3; //将3的值赋给变量a
    
    2. 复合的赋值运算符
    a += b;  //等价 a = a+b;
    x *= y+8;  //等价 x = x*(y+8);
    x %= 6   //等价 x = x%6;
    
    x %= y+2   //等同 x %= (y+2) 等价  x = x%(y+2);
               //注意:不要错写成 x=x%y+2;
    

    5. 条件运算符

    条件运算符:? :

    • 结合方向:右 → 左,优先级13
    • 唯一的三目运算符
    max = (a>b) ? a: b
    
    #include<stdio.h>
    int main()
    {
        int a=66, b=88;
        int max;
        max = (a>b) ? a: b; 
        printf("max = %d",max);
    }
    

    在这里插入图片描述

    在这里插入图片描述

    使用条件运算符需要注意的有一点:
    例题:
    设 x = 2,y = 3,z = 4,k = 5,则表达式“x < y ? x++ : z < k ? x : k”的值是( )
    A. 1 B.2 C.3 D.4
    分析:首先条件运算符的结合方向是:右 → 左,即可以写成 (x < y ? x++ : z < k) ? x : k 这种形式;先计算 x < y ? x++ : z 结果为真,然后再计算 x++ ? x : k;虽然结合方向是从右到左,但运算时是从左到右计算的。
    但是这题需要注意的是 x++ ? x : k 的结果是 x = 2,原因是x现参与条件运算,然后++
    结果:B

    6. 逗号运算符

    结合方向:左 → 右
    优先级:15(最低)
    在这里插入图片描述

    7. 强制类型转换运算符

    强制类型转换运算符:(类型)

    右 → 左,优先级2,单目运算符

    在这里插入图片描述

    8. 下标运算符

    下标运算符:[ ]

    • 用处:数组
    • 结合方向:左 → 右
    • 优先级:1
    1. 数组名 [下标]
    下标:可以是正常量 或 整型表达式
    int a[10]   //定义一个数组长度为10的数组
    a[0] = 66;  //对下标为0的元素赋值
    void sort(int array[],int n)  
    //选择排序中,定义sort函数,实参传递方式:地址传递
    

    9. 指针运算符

    指针运算符:&*

    结合方向:

    运算符与含义 对象个数 优先级
    &(取地址运算符) 1 单目运算符 2
    *(指针运算符) 1 单目运算符 2
    1】取地址运算符:&
         &a 是变量a的地址
    【2】指针运算符(或称“间接运算符”):*
         *p代表指针变量p指向的对象
    
    #include <stdio.h>
    int main()
    {
     
        int a = 666, *p;
        p = &a;   //使指针变量p 指向 变量a
          
        printf("%d\n",&a);   //输出变量a的 地址 
        printf("%d\n",p);   //输出指针变量p指向的 变量a的地址 
        printf("%d\n",*p);   //输出指针变量p指向的 变量a的值 
      
        return 0;
    }
    

    在这里插入图片描述

    10. 成员运算符

    成员运算符:->.

    运算符与含义 结合方向 优先级
    .(结构体成员运算符) 左 → 右 1
    ->(指向结构体成员运算符) 左 → 右 1

    用处:结构体数组(.和结构体指针(->

    成员运算符:->.
    #include<stdio.h>
    #include<string.h>
    
    int main()
    {
        struct Student     //声明结构体类型 struct Student 
        {
            int num;
            char name[20];
            char sex;
            float score;
        };
        struct Student stu;    //定义struct Student类型变量 stu 
        struct Student *p;     //定义指向struct Student类型数据的指针变量 p 
        p = &stu;              //p指向 stu 
    
       //对结构体成员赋值 
       stu.num = 10101;
       strcpy(stu.name,"Li Lin");   //用字符串复制函数给 stu.name赋值 
       stu.sex = 'M';
       stu.score = 88.8;
     
       //通过  结构体变量名stu  访问它的成员 
       printf("No.:%d\tname:%s\tsex:%c\tscore:%5.1f\n\n",stu.num, stu.name, stu.sex, stu.score);
    
       //通过  指向结构体变量的指针变量  访问它的成员
       printf("No.:%d\tname:%s\tsex:%c\tscore:%5.1f\n\n",(*p).num, (*p).name, (*p).sex, (*p).score);
       printf("No.:%d\tname:%s\tsex:%c\tscore:%5.1f\n\n",p->num, p->name, p->sex, p->score);
       
       return 0;
    }
    

    在这里插入图片描述

    如果p指向一个结构体变量stu
    下面3种用法等价:
    1. stu.成员名   stu.num
    2. (*p).成员名  (*p).num
    3. p->成员名    p->num
    

    11. 求字节运算符

    #include <stdio.h>
    
    // 【sizeof】 关键字:统计数据类型所占内存大小
    // 语法: sizeof(数据类型) 
    //       或 sizeof(变量) 
    // 整型占内存大小比较:short < int <= long <= long long
    
    int main()
    {
        short a = 10;
        printf("short  占用内存空间:%d\n", sizeof(short) ); 
        printf("short  占用内存空间:%d\n", sizeof(a) ); 
        
        int b = 10;
        printf("int    占用内存空间:%d\n", sizeof(int) ); 
        
        long c = 10;
        printf("long   占用内存空间:%d\n", sizeof(long) ); 
        
        long long d = 10;
        printf("long long  占用内存空间:%d\n", sizeof(long long) );
         
        return 0;
    }
    

    运行结果……………………………………………………

    在这里插入图片描述

    12. 位运算符 和 其它

    ① 位运算符: << >> ~ | ^ &

    • 位运算是指以二进制位为对象的运算,指针运算和位运算往往是编写系统软件会常常用到。
    • 参与位运算的对象只能是整型或字符型数据,不能是实型数据。
    • 位运算除了~,其余都是二目(元)运算符

    在这里插入图片描述

    ② 函数调用运算符:()

    • 函数调用运算符处于有:指向函数的指针、返回指针的函数
    • 优先级1
    int (*p)(int ,int ); //指向函数的指针:定义指向函数的指针变量p
    int *a(int x,int y); //返回指针的函数
    
    

    对于上面两种运算符,我只是看了一遍,并没有深入学习,所以这里就不作详细介绍了。
    在这里插入图片描述
    最后推荐文章:

    相见就是【猿分】
    在这里插入图片描述

    希望上面的内容对你能有有所帮助
    以上内容如有错误,请大家在评论区指正,谢谢支持,共同进步。 加油!!!
    如果你感觉我写的内容对你有一定的帮助,请给我点一个 【赞】作为您对我的鼓励, 谢谢!!

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 17
收藏数 334
精华内容 133
关键字:

c语言重要知识点总结

c语言 订阅