一文详解C语言关键字

前言

       关键字是C语言非常重要的一部分,熟练的掌握和使用关键字有助于我们更加熟悉了解C语言,同时C语言的关键字也是面试笔试中常考的内容。C语言的关键字共有32个,但并不是每个关键字都有坑,本篇文章将通过理论联系实际的方式为大家讲解C语言中易混易错以及常考的一些关键字。

一、C语言关键字详解

1. sizeof

       sizeof相信大家并不陌生,其作用就是计算变量所占用的内存空间大小。sizeof的用法看着和函数很相似,但sizeof的真实身份确是:sizeof既是关键字,也是运算符,但不是函数! 这点需要大家牢记。还有非常重要的一点就是 sizeof中的表示式编译器不会进行编译处理,其原因就是sizeof是在编译的时候执行的,而C语言的运算符计算是在程序运行的时候执行的,故 sizeof里面的表达式是不会被执行的。下面以一个实际的程序来为大家演示一下。

源代码:

#include <stdio.h>

int main()
{
    int a = 3, b = 0;

    b = sizeof(a++);
    
    printf("a = %d, b = %d\n", a, b);

    return 0;
}

运行结果:

a = 3, b = 4

       看上面的程序就知道,虽然在sizeof表达式中变量 a 进行了自增1操作,但是 ++ 运算符是在程序执行的时候运行的,而sizeof表达式是在程序编译的时候运行的,所以 ++ 操作并不会被执行。

2. const

       const关键字的作用就是将变量常量化。大家都知道变量是可以进行随意赋值的,但是常量不可以。而被const修饰的变量是不能够被赋值的,尽管如此,但是我们依旧有方法可以将其进行改变,看下面例子:
源代码:

#include <stdio.h>

int main()
{
   const int a = 3;

   //a = 4;    //程序报错,因为变量a被const修饰成只读的变量了。

   int *p = &a;
   *p = 8;

   printf("a = %d\n", a);

    return 0;
}

运行结果:

a = 8

       上面讲到const修饰的变量是不能够被赋值的,因此程序中注释的那一行会报错,这是合理的。在下面我们定义了一个指针指向变量 a ,并且通过指针的方式来改变变量 a 地址里面的内容,这样是合理的。我们可以这样来理解,首先定义一个变量 a , 那么这个变量 a 是具有可读可写属性的,用 const 对 a 进行修饰,可以理解成 const 去掉了变量 a 的写属性,只保留了读属性,所以不能再对 a 进行赋值了。接着我们定义了一个指针变量指向 a 的地址,这个新定义的指针变量没有被 const 修饰,所以具备可读可写属性,然后通过指针变量来对地址里面的值进行操作,相当于是间接改变了变量 a 里面的内容。所以const的作用可以简述成一句话,那就是 const修饰谁,谁不能被直接赋值,但是可以通过间接的方式来改变其内容。

3. static

static修饰的变量会存储在静态存储区,静态存储区默认值是0
static的三个作用:

  1. static修饰的局部变量只会被初始化一次。
  2. static修饰的全局变量只能在本文件中被使用,不能在其他文件中使用。
  3. static修饰的全局函数只能在本文件中被使用,不能在其他文件中使用。

作用1将在下面的程序示例为大家演示,作用2和作用3将结合 extern 关键字为大家演示。
源代码:

#include <stdio.h>

void func()
{
    static int a = 2;
    int b = 2;

    a++;
    b++;

    printf("a = %d, b = %d\n", a, b);
}

int main()
{
    int i = 0;

    for(i = 1; i <= 2; i++){
        func();
    }

    return 0;
}

运行结果:

a = 3, b = 3
a = 4, b = 3 

       上面程序中,就是调用了两次 func() 函数,func() 函数的功能就是定义两个变量,并且执行加1操作,然后打印输出。变量 a 因为被 static 修饰,所以 a 被存储在静态存储区,静态存储区中的内容是要等程序结束完才会被释放。并且 a 只会在程序第一次进来的时候被初始化一次,后续再进来的时候不会再执行初始化操作,且保留函数上一次退出的时候的值。而变量 b 没有被 static 修饰,所以存储在栈区,栈区中的内容会在该函数结束的时候被回收,所以每次执行func() 函数变量 b 都会被重新赋值。

4. extern

       extern一般只有在多文件编程的时候才会被用到,是用来修饰变量或函数的,并且告诉编译器,该变量或函数是在别的文件中被定义的,下面用一个实例来进行具体说明:
文件1源代码:

int a = 10;
int add(int a, int b)
{
	return a+b;
}

文件2源代码:

#include <stdio.h>

extern int a;
extern int add(int a, int b);

int main()
{
	printf("a = %d, sum = %d\n", a, add(10, 20));
}

文件1和文件2同时运行结果:

a = 10, sum = 30

       上面程序中在文件2中调用了文件1的变量和函数,因为变量和函数都是在文件1中定义的,所以我们想要引用到文件1中的变量或函数时就必须要用extern进行声明,否则就会报错。
       假设我们在文件1中将变量和函数用static进行修饰,文件2不变。
改变后的文件1源代码

static int a = 10;
static int add(int a, int b)
{
	return a+b;
}

       这个时候再同时运行文件1和文件2就会报错。报错的原因就是在文件2中找不到变量和函数。其原因就是被static修饰的变量或函数只能在该文件中使用。

5. volatile

       volatile的作用一句话概述的话就是防止编译器优化。 cpu读取变量的时候是先从内存中读取到寄存器,再从寄存器中读取变量的值,但是可能在一些情况下编译器认为某些变量的值没有发生变化,因此就省略了从内存中读取变量的操作,直接从寄存器中读取。但是这些值可能会被外部环境所改变,比如说是在中断或者别的线程里面改变,这个时候如果编译器没有及时更新变量在寄存器中的值就会导致读取错误。但如果将这个变量用volatile关键字修饰的话就可以保证cpu在读取变量的时候一定会从内存中读取到寄存器,这样就可以保证读取变量的值不出错。

6. typedef

       typedef的作用就是为已有类型取别名,注意typedef只是取别名,而不是创造出一个新的类型。
源代码:

#include <stdio.h>

int main()
{
    typedef int u32;

    u32 a = 10, b = 20;   //等价于 int a = 10, b = 20;

    printf("a+b = %d\n", a+b);
    
    return 0;
}

运行结果:

a+b = 30

       上面代码中使用 typedef 将 int 类型取名为 u32,对于编译器而言,只要是看到 u32 都会默认将其转换为 int 。取别名主要是方便我们来写和阅读代码,而并不会说是创造了新类型。

7. enum

       enum就是枚举类型,因为我们有的变量可能取值范围就是那么几个值,不会出现别的值。像这种情况下我们就最好使用枚举类型,注意的是枚举的值默认是从0开始的,后面的值以此增加,如果我们对枚举变量中某个值进行手动赋值,那么被手动赋值的后面那个值会在此基础上加1。举个实例为大家具体讲解:
源代码:

#include <stdio.h>

/*0, 1, 2, 3, 4, 5, 6*/
enum weekday{Monday, Tuesday, Wednesday, Thursday, Friday, Staurday, Sunday};

/*0, 1, 5, 6, 7*/
enum num{ONE, TWO, THREE=5, FOUR, FIVE};

int main()
{
    enum weekday day = 3;
    day = Thursday;

    enum num number = FIVE;
    printf("day = %d, number = %d\n", day, number);
    
    return 0;
}

运行结果:

day = 3, number = 7

8. continue

continue用法两大注意项:
(1)continue只能用在循环体当中。
(2)continue的作用是结束本次循环,进入到下一次循环。
源代码:

#include <stdio.h>

int main()
{
    int i;
    int a[5] = {12, 13, 5, 11, 10};

    for(i = 0; i < 5; i++){
        if(a[i] < 10){
            continue;
        }

        printf("a[%d] = %d\n", i, a[i]);
    }
    return 0;
}

运行结果:

a[0] = 12
a[1] = 13
a[3] = 11
a[4] = 10

       从上面程序可以看出,a[2] 的结果是 5,所以结束本次循环进入下次循环,所以当 i 的值为 2 的时候不会输出打印。

9. break

break用法两大注意项:
(1)break只能用于循环体或 switch…case 语句中。
(2)break的作用是跳出本循环体外,值得注意的是如果有多层循环嵌套的话,break是只能跳出它所在的那一层循环体。
源代码:

#include <stdio.h>

int main()
{
    int i;
    int a[5] = {12, 13, 5, 11, 10};

    for(i = 0; i < 5; i++){
        if(a[i] < 10){
            break;
        }

        printf("a[%d] = %d\n", i, a[i]);
    }
    return 0;
}

运行结果:

a[0] = 12
a[1] = 13

       从上面程序看,a[2] 的结果是 5,break就直接跳出了循环体,然后程序就结束运行了。因此从这里就能够看出continue关键字和break关键字最大的区别了,这两个关键字的区别也是常考的,大家可以好好熟悉。


       好了,C语言面试笔试中常考关键字为大家总结好了,希望大家都能够熟练的掌握其用法,如果大家对文中有啥异议或者不解,欢迎大家在下面留言,可以共同讨论哦~

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值