• C语言参数类型


    1、非浮点数规定- -规定就不要过于去想为什么,就是这么规定的

    cpu的位数代表着cpu一次性能够处理的数据的位数,而CPU是通过地址总线、数据总线、控制总线三条线与内存进行数据传输与操作。我们要明白,指针就是地址,地址就是指针。 而地址是内存单元的编号。所以,一个指针占几个字节,等于是一个地址的内存单元编号有多长,就是地址总线的宽度。

    int的长度,是由硬件和系统共同决定的。
    当年的dos是运行在16位CPU下的,他的int是两个字节,
    win95是运行在32位CPU下的,但是win95还是16位的系统设计,所以他的int是2个字节,
    到2000,NT,XP,cpu是32位的,windows也支持32位,所以他的int是4字节

    语言并没有规定类型的长度,但是有一些规则,比如:char不论在什么时候都是一个字节(即8个bit),int永远比char长,长整型至少和整型一样长,整型至少和短整型一样长(short<=int<=long)。

    数据类型16bit编译器(字节)32bit编译器(字节)64bit编译器(字节)
    char111
    short int222
    int/unsigned int,依赖于编译器244
    long/unsigned long,依赖于编译器448
    Char *(指针类型),依赖于编译器248
    float444
    double888

    综上:
    从16bit升级至32bit时,int所占的字节数将发生变化。
    从32bit升级至64bit时,long所占的字节数将发生变化。
    指针占的位数=地址总线的宽度,
    数据总线的宽度=字长=cpu的位数=cpu一次性能够处理的数据的位数

    最后提一下取值范围

    数据类型取值范围
    signed char = char-128 ~ +127 (1 Byte)
    signed short = short-32767 ~ + 32768 (2 Bytes)
    unsigned short0 ~ 65536 (2 Bytes)
    signed int = int-2147483648 ~ +2147483647 (4 Bytes)
    unsigned int0 ~ 4294967295 (4 Bytes)

    大部分体系结构上, char默认是带符号的,它可以自-128到127之间取值。也有一些例外,比如ARM体系结构上,char 就是不带符号的,它的取值范围是0~ 255。

    2、浮点数规定——二进制版科学计数法

    根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:
    (-1)^S * M * 2^E
    (-1)^s表示符号位,当s=0,V为正数;当s=1,V为负数。
    M表示有效数字,大于等于1,小于2。
    2^E表示指数位。
    举例来说: 十进制的5.0,写成二进制是 101.0 ,相当于 1.01×2^2 。 那么,按照上面V的格式,可以得出s=0,M=1.01,E=2。
    十进制的-5.0,写成二进制是 -101.0 ,相当于 -1.01×2^2 。那么,s=1,M=1.01,E=2。

    IEEE 754规定: 对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。
    在这里插入图片描述
    对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。
    在这里插入图片描述
    IEEE 754对有效数字M和指数E,还有一些特别规定。 前面说过, 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形式,其中xxxxxx表示小数部分。
    IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。
    比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。
    以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字。至于指数E,情况就比较复杂。
    首先,E为一个无符号整数(unsigned int) 这意味着,如果E为8位,它的取值范围为0255;如果E为11位,它的取值范围为02047。但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。比如,2^10的E 是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。

    然后,指数E从内存中取出还可以再分成三种情况:
    a)E不全为0或不全为1
    这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。 比如: 0.5(1/2)的二进制形式为0.1,由于规定正数部分必须为1,即将小数点右移1位,则为1.0*2^(-1),其阶码为-1+127=126,表示为01111110,而尾数1.0去掉整数部分为0,补齐0到23位00000000000000000000000,则其二进制表示形式为: 00 01111110 00000000000000000000000

    b)E全为
    这时,浮点数的指数E等于1-127(或者1-1023)即为真实值, 有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。

    c)E全为1
    这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);
    好了,关于浮点数的表示规则,就说到这里。

    3、局部变量和全局变量之间的区别

    局部变量在函数内定义,全局变量在函数外定义
    在这里插入图片描述

    • C/C++程序内存分配的几个区域:
    1. 栈区(stack):在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。 栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返回地址等。
    2. 堆区(heap):一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。分配方式类似于链表。
    3. 数据段(静态区)(static)存放全局变量、静态数据。程序结束后由系统释放。
    4. 代码段:存放函数体(类成员函数和全局函数)的二进制代码。
    • 有了这幅图,我们就可以更好的理解在《C语言初识》中讲的static关键字修饰局部变量的例子了。实际上普通的局部变量是在栈区分配空间的,栈区的特点是在上面创建的变量出了作用域就销毁。但是被static修饰的变量存放在数据段(静态区),数据段的特点是在上面创建的变量,直到程序结束才销毁所以生命周期变长

    1)局部变量分为:静态局部变量、全局局部变量

    a)静态局部变量
    在介绍静态局部变量之前,我们先了解一个概念:静态,在C语言中我们使用关键字static来表示静态,当我们在定义变量时,一般的说在函数内部定义的变量我们称之为局部变量,在定义时对其前面加上关键字static,则此局部变量就是静态局部变量 ,我们举个简单的例子:

    void Func()
    {
    	static int n;  //定义一个整形变量的静态局部变量n。
    }
    
    • 1
    • 2
    • 3
    • 4

    按照其字面意思,就是它的作用域只对局部有用,所以一般的说静态局部变量的作用域就是函数内部,只是在某一个块中发挥作用,而静态局部变量的生命周期是:函数进入时创建,程序退出时消亡,这里就涉及到计算机为其分配的内存区域。
    当我们创建一个项目时,计算机会将欲分配的内存区域大致分为4个区域:第一个是代码区(段),第二个是全局(静态)变量区,第三个是栈,第四个是堆。而我们所定义的各种变量会按照其属性分别存放在不同的区域。就比如说,静态局部变量会存放在全局(静态)变量区,而普通局部变量会存放在栈内。

    b)普通局部变量
    对于普通局部变量,就是我们一般的在函数体内或者在主函数main()内部定义的变量,其作用域和静态局部变量是一样的,都只作用于某一个块内,或者说某一个函数体内。它的生命周期是:函数进入时创建,函数退出时消亡,举个简单的例子:

    void Func()
    {
    int n; //定义一个整形变量的普通局部变量n。
    }

    【注】对于普通局部变量和静态局部变量来说,没有链接属性这个概念,是因为局部变量只是在函数体内作用,并不能将其通过链接扩大其作用域。

    总结:对于局部变量,通俗点说就是定义在函数内部的变量,其作用域只是函数内部,退出函数体就失去其作用,若在对其进行调用程序会出错,例如:

    int Sumc(int a, int b)
    {
    	int sum;  //定义一个整形变量的局部变量sum
    	sum = a + b;  //变量a,b,sum均为局部变量,只在函数Sumc中发挥作用
    	return sum;  //返回两个整数a,b的和
    }
    int main()
    {
    	int n;  //定义一个整形变量的局部变量n,只在主函数main()中发挥作用
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2)全局变量分为:普通全局变量,静态全局变量

    a)普通全局变量
    全局变量,通俗的理解,就是其在全局也即整个文件中发挥作用 ,从其作用域理解,它在定义的时候,就必须定义在函数体外部,或者主函数的外部,对于普通的全局变量,它的生命周期是在程序运行时创建,在程序退出时消亡。

    【注】对于全局变量,不论是普通全局变量,还是静态全局变量,其内存区域均在全局(静态)变量区。

    b)静态全局变量
    类似于静态局部变量的定义,在定义全局变量的时候在其前面加上关键字static,即为静态全局变量。对于静态全局变量,它的作用域是整个文件,生命周期是程序运行时创建,程序退出时消亡,它存储在全局(静态)变量区,举个简单的例子:

    static int n = 0; //定义一个静态全局变量n,并且初始化为0,其作用域是整个文件,也就是对函数Func和main均可用
    int m = 0; //定义一个普通全局变量m,并且初始化为0,其作用域是整个文件
    void Func()
    {
    int n; //定义一个整形变量的普通局部变量n,其作用域是函数Func()内部
    }
    int main()
    {
    char str; //定义一个char类型的普通局部变量str,其作用域是主函数main()内部
    }

    如下代码,我们在函数体外定义一个全局变量sum,此时,可以在函数Func中使用,也可以在主函数main中使用。

    c)全局变量和局部变量的比较
    1.比较

    生命周期作用域默认值内存区域链接属性
    普通局部变量函数进入时创建,函数退出时消亡函数内随机值
    静态局部变量函数进入时创建,程序退出时消亡函数内0全局(静态)变量区
    普通全局变量程序运行时创建,程序退出时消亡整个文件内0全局(静态)变量区
    静态全局变量程序运行时创建,程序退出时消亡整个文件内0全局(静态)变量区

    2.静态关键字:static
    static 是 C/C++ 中很常用的修饰符,它被用来控制变量的存储方式和可见性。在C语言中,关键字static主要定义全局静态变量、定义局部静态变量、定义静态函数。
    static可以修改变量或者函数的声明周期,默认值,内存区域,链接属性。

    举个简单的例子:

    int a;   //普通全局变量  程序创建时生成,程序退出时消亡  全局(静态)变量区  整个文件内  外部  默认值:0
    static int b;  //静态全局变量  程序创建时生成,程序退出时消亡  全局(静态)变量区  整个文件内  内部(加extern变为外部)  默认值:0
    const int c = 10;   //全局变量(默认为静态) 内部  程序创建时生成,程序退出时消亡  
    int main()
    {
    	int d;  //普通局部变量  函数(代码块)创建时生成,函数退出时消亡   函数内   栈内   默认值:随机值
    	static int e;  //静态局部变量  函数创建时生成,程序退出时消亡   函数内    全局(静态)变量区       
    	const int f = 20;  //局部变量  函数创建时生成,函数退出时消亡   函数内 
    	for (int i = 0; i < 10; i++)  //i是局部变量  块创建时生成,块结束时消亡  块内可见
    	{
    		printf("%d\n", i);  
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3)extern:声明外部全局变量

    extern:声明外部全局变量,注意:extern只能用于声明,不能用于定义。(个人理解:声明可以多次,定义只能一次。毕竟全局范围是所有文件,影刺所有文件中只能有一次定义)

    extern工作原理:先会去当前文件下查找有没有对应全局变量,如果没有,才回去其他文件查找
    extern的原理很简单,就是告诉编译器:“你现在编译的文件中,有一个标识符虽然没有在本文件中定义,但是它是在别的文件中定义的全局变量,编译器你要放行!”

    前面的全局变量,全局即整个文件。
    有了extern,就可以声明以所有文件为全局范围的全局变量变量。

  • 相关阅读:
    【紫光同创国产FPGA教程】【PGC1/2KG第六章】密码锁实验例程
    直播绿幕抠图的例子(绿幕抠图直播实例参考)
    c语言-浅谈指针(3)
    读书笔记:多Transformer的双向编码器表示法(Bert)-3
    zabbix
    【分享】“微信小商店“在集简云平台集成应用的常见问题与解决方案
    基于信息检索和深度学习结合的单元测试用例断言自动生成
    业务安全及案例实战
    半平面求交 - 洛谷 - UVA1475 Jungle Outpost
    Webpack 安装教程
  • 原文地址:https://blog.csdn.net/weixin_55255438/article/details/126710438