C语言语法进阶

条件运算符

条件运算符是 C 语言中唯一的一种三目运算符。三目运算符代表有三个操作数;双目 运算符代表有两个操作数,如逻辑与运算符就是双目运算符;单目运算符代表有一个操作数, 如逻辑非运算符就是单目运算符。运算符也称操作符。三目运算符通过判断问号之前的表达 式的真假,来确定整体表达式的值,如下例所示,如果 a>b 为真,那么三目表达式整体的 值为 a,所以 max 的值等于 a,如果 a>b 为假,那么三目表达式整体的值为 b,所以 max 的值等于 b。

逗号运算符

逗号运算符的优先级最低,我们需要掌握的是,逗号表达式的整体值是最后一个表达式 的值。请看下面实例

cpp 复制代码
#include <iostream>
using namespace std;
int main() {
    int a,b,max;
    while (scanf("%d %d",&a,&b))
    {
        max=a>b?a:b;
        printf("max=%d\n",max);
    }
    int i,j;
    i=10;
    j=1;
    if(i,j)//逗号表达式整体的值是最后一个表达式的值
    {
        printf("i am coming");
    }
    return 0;
}

自增自减运算符

自增、自减运算符和其他运算符有很大的区别,因为其他运算符除赋值运算符可以改变变 量本身的值外,不会有这种效果。自增、自减就是对变量自身进行加 1、减 1 操作,那么有了 加法和减法运算符为什么还要发明这种运算符呢?原因是自增和自减来源于 B 语言,当时 Ken Thompson 和 Dennis M. Ritchie(C 语言的发明者)为了不改变程序员的编写习惯,在 C 语言 中保留了 B 语言中的自增和自减。因为自增、自减会改变变量的值,所以自增和自减不能用于 常量! 下例中的 j=i++>-1,对于后++或者后--,首先我们需要去掉++或--运算符,也就是首先计 算 j=i>-1,因为 i 本身等于-1,所以得到 j 的值为 0,接着单独计算 i++,也就是对 i 加 1,所以 i 从-1 加 1 得到 0,因此 printf("i=%d,j=%d\n",i,j);语句的执行结果是 0 和 0。请看下例

自增自减运算符与取值运算符

虽然上面已经对自增自减运算符进行了讲解,但是当自增自减运算符与取值运算符结合 使用时,会有一定的难度,原理与上面是一致的。我们再次来练习一下

cpp 复制代码
#include <iostream>
#include <stdio.h>
int main() {
    int i=-1,j;
    //5++; 这样编译不通 报错误
    j=i++>1;
    printf("i=%d j=%d\n",i,j);

    int a[3]={2,6,9};
    int *p;
    p=a;
    j=*p++;//先把*p的值赋给j p再加1
    printf("a[0]=%d j=%d *p=%d\n",a[0],j,*p);
    j=p[0]++;
    printf("a[0]=%d j=%d *p=%d\n",a[0],j,*p);
    printf("a[0]=%d a[1]=%d a[2]=%d",a[0],a[1],a[2]);
    return 0;
}

位运算符

位运算符>、~、|、^、&依次是左移、右移、按位取反、按位或、按位异或、按位与。 位运算符只能用于对整型数据进行操作。 左移:高位丢弃,低位补 0,相当于乘以 2。工作中很多时候申请内存时会用左移,例如要 申请 1GB 大小的空间,可以使用 malloc(1>1,得到的是-4,但-7>>1 得到的并不是-3 而是-4。另外,对 于-1 来说,无论右移多少位,值永远为-1。 异或:相同的数进行异或时,结果为 0,任何数和 0 异或的结果是其本身。 按位取反:数位上的数是 1 变为 0,0 变为 1。 按位与和按位或:用两个数的每一位进行与和或。

cpp 复制代码
#include <iostream>
#include <stdio.h>
int main() {
     short i=5;
     short j;
     j=i<<1;//一个变量移动以后自身位置不会变化
    printf("j=%d\n",j);//左移×2
    j=i>>1;
    printf("j=%d\n",j);//右移除以2
    i = 0x8011;
    unsigned short s=0x8011;
    unsigned short r=0;
    j= i >> 1;//对i进行右移
    r= s >> 1;//对s右移
    printf("j=%d r=%u\n",j,r);//结果不一样
    i=5,j=7;
    printf("i & j=%d\n",i&j);
    printf("i | j=%d\n",i|j);
    printf("i ^ j=%d\n",i^j);
    printf("~i=%d\n",~i);
    return 0;
}

switch 选择语句

判断的一个变量可以等于几个值或几十个值时,使用 if 和 else if 语句会导致 else if 分支非 常多,这时可以考虑使用 switch 语句,switch 语句的语法格式如下:

switch (表达式)

{

case 常量表达式 1:语句 1

case 常量表达式 2:语句 2

... case 常量表达式n:语句 n

default :语句 n+1

}

下面来看一个使用 switch 语句的例子。如例 1 所示,输入一个年份和月份,然后打印对应 月份的天数,如输入一个闰年和 2 月,则输出为 29 天。具体代码如下所示,对应的电子附件项 目名称为"switch 月份 1",读者会发现,switch 语句中 case 后面的常量表达式的值不是按照 1 到 12 的顺序排列的,这里要说明的是,switch 语句匹配并不需要常量表达式的值有序排列, 输入值等于哪个常量表达式的值,就执行其后的语句,每条语句后需要加上 break 语句,代表 匹配成功一个常量表达式时就不再匹配并跳出 switch 语句

cpp 复制代码
#include <iostream>

int main() {
    int mon,year;
    while (scanf("%d %d",&year,&mon)) {
        switch (mon) {
            case 2:
                printf("mon=%d is %d days\n",mon,28+(year%4==0&&year%100!=0||year%400==0));
                break;
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                printf("mon=%d is 31 days\n",mon);
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                printf("mon=%d is 30 days\n",mon);
                break;
            default:
                printf("error\n");
        }
    }
    return 0;
}

do while 循环讲解

do while 语句的特点是:先执行循环体,后判断循环条件是否成立。其一般形式为

do {

循环体语句;

}while (表达式);

执行过程如下:首先执行一次指定的循环体语句,然后判断表达式,当表达式的值为非零 (真) 时,返回重新执行循环体语句,如此反复,直到表达式的值等于 0 为止。例 3 是使用 do while语句计算 1到 100之间所有整数之和的例子,do while语句与 while语句的差别是,do while 语句第一次执行循环体语句之前不会判断表达式的值,也就是如果 i 的初值为 101,那么依然会 进入循环体。实际工作中 do while 语句应用较少。

cpp 复制代码
#include <iostream>

int main() {
    int i=1,total=0;
    do {
        total=total+i;
        i=i+1;
    } while (i<=100);
    printf("total=%d",total);
    return 0;
}

二维数组讲解(408 大纲范围内,初试小概率考)

二维数组定义的一般形式如下: 类型说明符 数组名[常量表达式][常量表达式]; 例如,定义 a 为 3×4(3 行 4 列)的数组,b 为 5×10(5 行 10 列)的数组: float a[3][4],b[5][10]; 可以将二维数组视为一种特殊的一维数组:一个数组中的元素类型是一维数组的一维数组。 例如,可以把二维数组 a[3][4]视为一个一维数组,它有 3 个元素 a[0]、a[1]和 a[2],每个 元素又是一个包含 4 个元素的一维数组,如图 1 所示。 二维数组中的元素在内存中的存储规则是按行存储,即先顺序存储第一行的元素,后顺序 存储第二行的元素,数组元素的获取依次是从 a[0][0]到 a[0][1],直到最后一个元素 a[2][3]。 图 2 中显示了存储二维数组 a[3][4]中每个元素时的顺序。

cpp 复制代码
#include <iostream>

int main() {
    //可以通过调试查看元素存放的顺序
    int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
    printf("sizeof(a)=%d\n",sizeof (a));//二维数组大小
    printf("a[3][4]=%d\n",a[2][3]);//最后一个元素
    return 0;
}

二级指针讲解(不在 408 大纲范围,408 初试不考,初试考 C 的学校可能需要,机试用到概率极低)

如果掌握了 C++的引用,其实不需要去学习二级指针,对于考研必要性很低,二级指 针是指针的指针,二级指针的作用是服务于一级指针变量,对一级指针变量实现间接访问。 下面我们通过一个实例来让大家理解一下二级指针。

cpp 复制代码
#include <iostream>

int main() {
    int i=10;
    int *p;
    int **p1;
    p=&i;
    p1=&p;
    printf("sizeof(p1)=%d\n",sizeof (p1));
    printf("**p1=%d *p=%d",**p1,*p);
    return 0;
}
相关推荐
丫头,冲鸭!!!9 分钟前
B树(B-Tree)和B+树(B+ Tree)
笔记·算法
Re.不晚14 分钟前
Java入门15——抽象类
java·开发语言·学习·算法·intellij-idea
ULTRA??23 分钟前
C加加中的结构化绑定(解包,折叠展开)
开发语言·c++
凌云行者1 小时前
OpenGL入门005——使用Shader类管理着色器
c++·cmake·opengl
凌云行者1 小时前
OpenGL入门006——着色器在纹理混合中的应用
c++·cmake·opengl
为什么这亚子1 小时前
九、Go语言快速入门之map
运维·开发语言·后端·算法·云原生·golang·云计算
1 小时前
开源竞争-数据驱动成长-11/05-大专生的思考
人工智能·笔记·学习·算法·机器学习
~yY…s<#>1 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode
可均可可2 小时前
C++之OpenCV入门到提高004:Mat 对象的使用
c++·opencv·mat·imread·imwrite
幸运超级加倍~2 小时前
软件设计师-上午题-16 算法(4-5分)
笔记·算法