• 【C语言|关键字】C语言32个关键字详解(4)——其他(typedef、sizeof)


    😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
    🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
    🤣本文内容🤣:🍭介绍标准C语言的32个关键字🍭
    😎金句分享😎:🍭有机会一定要试试,其实试错的成本并不高,而错过的成本很高🍭

    C语言32个关键字详解(1):数据类型部分(char、short、int、long、float、double、struct、union、enum、void)
    C语言32个关键字详解(2):修饰类型部分(auto、signed、unsigned、static、extern、const、register、volatile)
    C语言32个关键字详解(3):结构语句部分(if、else、switch、case、default、do、while、for、break、continue、return、goto)
    C语言32个关键字详解(4):其他(typedef、sizeof)


    在这里插入图片描述

    🎄一、概述

    C语言的关键字有32个,我将它主要分成下面四个方面来介绍。

    功能关键字
    类型(10个)char、short、int、long、float、double、struct、union、enum、void
    修饰类型(8个)auto、signed、unsigned、static、extern、const、register、volatile
    结构语句(12个)if、else、switch、case、default、do、while、for、break、continue、return、goto
    其他(2个)typedef、sizeof

    前面介绍了char、short、int、long、float、double、struct、union、enum、void、auto、signed、unsigned、static、extern、const、register、volatile、 if、else、switch、case、default、do、while、for、break、continue、return、goto

    这篇文章主要介绍最后两个关键字typedef、sizeo


    在这里插入图片描述

    🎄二、typedef 关键字

    ✨2.1 typedef 给类型取别名

    typedef 的名字来看,会以为它是定义新的数据类型,但实际上 typedef 的真正意思是给一个已经存在的数据类型(注意:是类型不是变量)取一个别名,而非定义一个新的数据类型。常用来给基本类型、指针类型、函数指针取别名;

    常见的用法:
    1、给基本数据类型重命名,代码如下:

    typedef signed char        int8_t;
    typedef short              int16_t;
    typedef int                int32_t;
    typedef long long          int64_t;
    typedef unsigned char      uint8_t;
    typedef unsigned short     uint16_t;
    typedef unsigned int       uint32_t;
    typedef unsigned long long uint64_t;
    
    uint64_t u64_i = 0; // 等同于 unsigned long long u64_i = 0;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2、给结构体、结构体指针类型取别名:

    typedef struct student
    {
    //...code
    }Stu_st, *Stu_pst;
    
    Stu_st stu; // 等同于 struct student stu;
    Stu_pst pStu; // 等同于 struct student* pStu;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3、给函数指针类型取别名:

    typedef unsigned int (*fn_callback)(void*,void*);
    fn_callback fn_callback; // 定义一个函数指针 fn_callback
    
    • 1
    • 2

    ✨2.2 typedef 的类型 和 const 一起使用

    首先,我们知道const在类型前或后去修饰一个变量时,效果是一样的。
    如: const int i;int const i; 两个语句都是表示变量 i 的值是只读的,不允许被改变。

    const*前面表示修饰的指针指向的对象是只读的,const*后面表示指针是只读的,如:
    const int * pI; 表示 pI 指向的对象的值是只读的,不能被改变;
    int * const pI; 表示 pI 变量的值是只读的,不能被改变;

    那么下面的代码中,先将int *重命名为 pInt。请问 const_pIntpInt_const 分别表示哪些是只读的?

    typedef int * pInt;
    const pInt const_pInt;
    pInt const pInt_const;
    
    • 1
    • 2
    • 3

    可能你会认为const_pInt表示指针指向的对象是只读的,而pInt_const表示指针本身是只读的。答案是,const_pIntpInt_const 都是表示指针本身是只读的。因为编译器单纯地把pInt当作一个类型来处理,所以它只会限制变量只读,不可修改。
    可以用下面代码测试验证:

    // typedef.c
    #include 
    typedef int * pInt;
    int main()
    {
    	int i=0, j=0;
    	const pInt const_pInt = &i;
    	pInt const pInt_const = &i;
    	//const_pInt = &j; //报错:assignment of read-only variable ‘const_pInt’
    	//pInt_const = &j; //报错:assignment of read-only variable ‘pInt_const’
    	*const_pInt = 1;
    	*pInt_const = 2;
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    原文链接:https://blog.csdn.net/wkd_007/article/details/133997095


    ✨2.3 typedef 的类型 和 #define 的区别

    如果将上面的typedef int * pInt;替换成#define pInt int*const_pIntpInt_const 分别表示哪些是只读的?

    答案是,const_pInt表示指针指向的对象是只读的,而pInt_const表示指针本身是只读的。因为宏定义会在预处理阶段替换成int*,就变成了const int * const_pInt;int * const pInt_const;

    可以用下面的代码测试验证:

    //typdef_define.c
    #include 
    #define pInt int*
    int main()
    {
    	int i=0, j=0;
    	const pInt const_pInt = &i;
    	pInt const pInt_const = &i;
    	const_pInt = &j;
    	//pInt_const = &j; //报错:assignment of read-only variable ‘pInt_const’
    	//*const_pInt = 1; //报错:assignment of read-only location ‘*const_pInt’
    	*pInt_const = 2;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    因为宏定义只是进行简单的字符串替换,所以宏定义的指针类型,每次只能成功定义一个指针变量。
    例如:下面代码中,pI变量是int*类型的,而i变量则是int类型的;
    pSpSh都是short *类型的。

    #define pInt int*
    typedef short * pShort;
    pInt pI,i;
    pShort pS,pSh;
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    🎄三、sizeof 关键字

    ✨3.1 sizeof 是关键字,不是函数

    sizeof 关键字常被误以为是函数,实际上,它是一个关键字。作用是在编译时计算给定类型或变量的大小,并返回占用空间大小,返回的值是long unsigned int类型的。

    在计算指定类型大小时,需要加(),计算指定变量的大小时可以不用(),下面代码中,sizeof(int), sizeof(i), sizeof i 都是正确的,如果写成sizeof int 就是错误的,因为返回的值是long unsigned int,用%lu打印。

    #include 
    int main()
    {
        int i = 0;
        printf("sizeof(int)=%lu, sizeof(i)=%lu sizeof i = %lu\n",sizeof(int), sizeof(i), sizeof i);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    注意:
    1、sizeof i 这个语句是正确的,就可以证明 sizeof 是关键字而不是函数,因为不能这样调用;
    2、一般情况下,使用sizeof时,建议带上()


    ✨3.2 sizeof 与指针、数组的使用

    sizeof 关键字计算指针的值时,在32位系统永远返回4,在64位系统永远返回8;

    int *p = NULL;
    sizeof(p)的值是多少?
    sizeof(*p)呢?
    
    int a[100];
    sizeof (a) 的值是多少?
    sizeof(a[100])呢? //请尤其注意本例。
    sizeof(&a)呢?
    sizeof(&a[0])呢?
    sizeof((&a)[0])呢?
    
    int b[100];
    void fun(int b[100])
    {
    	sizeof(b);// sizeof (b) 的值是多少?
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    阅读上面代码,试着判断各个sizeof的值是多少?答案在下文给出,可以自己先判断,看看能否准确!!!

    在判断sizeof的值时,要清楚指定的变量是什么类型?

    以32位系统为例,只要是指针,其sizeof的值就是4;
    只要是数组名,sizeof大小就是整个数组的大小;
    只要是数组元素,sizeof大小就是单个数元素的大小;
    如果数组作用函数参数,那么sizeof(数组名)的大小则等于指针的大小;

    答案:在64位系统运行下面代码,打印的答案如下:

    sizeof(p)=8 sizeof(*p)=4
    sizeof(a)=400, sizeof(a[100])=4, sizeof(&a)=8, sizeof(&a[0])=8, sizeof((&a)[0])=400
    sizeof(b)=8
    
    • 1
    • 2
    • 3
    // sizeof_arr.c
    #include 
    
    void fun(int b[100])
    {
    	printf("sizeof(b)=%lu\n",sizeof(b));
    }
    
    int main()
    {
    	int *p = NULL;
    	printf("sizeof(p)=%lu sizeof(*p)=%lu\n",sizeof(p),sizeof(*p));
    
    	int a[100];
    	printf("sizeof(a)=%lu, sizeof(a[100])=%lu, sizeof(&a)=%lu, sizeof(&a[0])=%lu, sizeof((&a)[0])=%lu\n",
    		sizeof(a), sizeof(a[100]), sizeof(&a), sizeof(&a[0]), sizeof((&a)[0]));
    
    	int b[100];
    	fun(b);
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    ✨3.2 sizeof 与复杂类型

    先看看下面这些变量的类型是什么?

    char a[10][20];
    char (*pa)[5];
    char (*p_fun)(char *);
    int (*(*pa_fun)[5])(char *);
    
    • 1
    • 2
    • 3
    • 4

    把变量名去掉,得到的就是类型了,对于类型表示什么,在后面讲指针的文章会介绍。我们把这些复杂的类型给到sizeof,居然可以计算出类型占用的内存大小,看例子:

    #include 
    
    int main()
    {
    	char a[10][20];
    	char (*pa)[5];
    	char (*p_fun)(char *);
    	int (*(*pa_fun)[5])(char *);
    	printf("sizeofType [%lu] [%lu] [%lu] [%lu]\n",sizeof(char [10][20]), sizeof(char (*)[5]),sizeof(char (*)(char *)),sizeof(int (*(*)[5])(char *)));
    	printf("sizeof Val [%lu] [%lu] [%lu] [%lu]\n",sizeof(a), sizeof(pa),sizeof(p_fun),sizeof(pa_fun));
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

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


    在这里插入图片描述

    🎄四、总结

    本文主要介绍C语言的两个关键字typedef、sizeof,结合前面的30个,C语言的32个关键字全部介绍完了。

    在这里插入图片描述
    如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

  • 相关阅读:
    C++ 智能指针最佳实践&源码分析
    LeetCode --- 1252. Cells with Odd Values in a Matrix 解题报告
    09.Tornado_获取请求参数
    图的邻接矩阵存储 C语言实现BFS
    GANs生成对抗网络的学习
    [36c3 2019]includer
    R语言绘制矩阵散点图
    封闭岛屿数量 -- 二维矩阵的dfs算法
    javascript 赋值运算符、一元运算符、运算优先级详细解析与代码实例
    Springboot Vue个人简历网站系统java项目源码
  • 原文地址:https://blog.csdn.net/wkd_007/article/details/133997095