从内存理解C语言中变量的存储类型

合集下载

(整理)第04章 变量的存储类型

(整理)第04章 变量的存储类型

第4章变量的存储类型4.1 概述C语言中的变量具有两种属性:根据变量所持有数据的性质不同而分为各种数据类型;根据变量的存储方式不同而分为各种存储类型.变量的数据类型决定了该变量所占内存单元的大小及形式;变量的存储类型规定了该变量所在的存储区域,因而规定了该变量作用时间的长短,即寿命的长短,这种性质又称为"存在性".变量在程序中说明的位置决定了该变量的作用域,即在什么范围内可以引用该变量,"可引用"又称为"可见",所以这种性质又称为"可见性".计算机的内存和CPU中的寄存器都可以存放数据,变量究竟存放在何处则由存储类来决定.存储类型用来说明变量的作用域,生存期,可见性和存储方式.下面解释几个概念:1 作用域:是该变量在其上有定义的程序部分,通俗的说,即该变量起作用的某个程序区域。

2 变量的生存期:是指它从产生到消亡的存在时间,即变量从定义开始到它所占有的存储空间被系统收回为止的这段时间。

3 变量的可见性的含义:在某个程序区域,可以对变量进行访问(或称存取)操作,我们则称该变量在该区域为可见的,否则为不可见的。

再引入几个概念:4 全局变量和局部变量在一个函数内部或复合语句内部定义的变量叫内部变量,又称为"局部变量"。

在函数外定义的变量称为外部变量,又称为"全局变量"。

如:int x ;void main( ){int a, b;float c;……..}x 定义在函数外,是全局int 型变量a,b定义在main()函数内是局部int 型变量c 定义在main()函数内是局部float 型变量6 动态存储变量和静态存储变量。

在程序运行期间,所有的变量均需占有内存,有的是临时占用内存,有的是整个程序运行过程中从头到尾占用内存。

对于在程序运行期间根据需要进行临时性动态分配存储空间的变量称为"动态存储变量",对于在程序运行期间永久性占用内存的变量称为"静态存储变量".一个正在运行的程序可将其使用内存的情况分为如下三类(如下图):程序代码区: 程序的指令代码存放在程序代码区。

C语言中float,double类型,在内存中的结构(存储方式).

C语言中float,double类型,在内存中的结构(存储方式).

C语⾔中float,double类型,在内存中的结构(存储⽅式).从存储结构和算法上来讲,double和float是⼀样的,不⼀样的地⽅仅仅是float是32位的,double是64位的,所以double能存储更⾼的精度。

任何数据在内存中都是以⼆进制(0或1)顺序存储的,每⼀个1或0被称为1位,⽽在x86CPU上⼀个字节是8位。

⽐如⼀个16位(2 字节)的short int型变量的值是1000,那么它的⼆进制表达就是:00000011 11101000。

由于Intel CPU的架构原因,它是按字节倒序存储的,那么就因该是这样:11101000 00000011,这就是定点数1000在内存中的结构。

⽬前C/C++编译器标准都遵照IEEE制定的浮点数表⽰法来进⾏float,double运算。

这种结构是⼀种科学计数法,⽤符号、指数和尾数来表⽰,底数定为2——即把⼀个浮点数表⽰为尾数乘以2的指数次⽅再添上符号。

下⾯是具体的规格:符号位阶码尾数长度float 1 8 23 32double 1 11 52 64临时数 1 15 64 80由于通常C编译器默认浮点数是double型的,下⾯以double为例:共计64位,折合8字节。

由最⾼到最低位分别是第63、62、61、……、0位:最⾼位63位是符号位,1表⽰该数为负,0正; 62-52位,⼀共11位是指数位; 51-0位,⼀共52位是尾数位。

按照IEEE浮点数表⽰法,下⾯将把double型浮点数38414.4转换为⼗六进制代码。

把整数部和⼩数部分开处理:整数部直接化⼗六进制:960E。

⼩数的处理: 0.4=0.5*0+0.25*1+0.125*1+0.0625*0+…… 实际上这永远算不完!这就是著名的浮点数精度问题。

所以直到加上前⾯的整数部分算够53位就⾏了(隐藏位技术:最⾼位的1 不写⼊内存)。

如果你够耐⼼,⼿⼯算到53位那么因该是:38414.4(10)=1001011000001110.0110101010101010101010101010101010101(2)科学记数法为:1.001……乘以2的15次⽅。

C语言中局部变量和全局变量等在内存中的存放位置

C语言中局部变量和全局变量等在内存中的存放位置

C语言中局部变量和全局变量变量的存储类别(static,extern,auto,register)8.8局部变量和全局变量在讨论函数的形参变量时曾经提到,形参变量只在被调用期间才分配内存单元,调用结束立即释放。

这一点表明形参变量只有在函数内才是有效的,离开该函数就不能再使用了。

这种变量有效性的范围称变量的作用域。

不仅对于形参变量,C语言中所有的量都有自己的作用域。

变量说明的方式不同,其作用域也不同。

C语言中的变量,按作用域范围可分为两种,即局部变量和全局变量。

8.8.1局部变量局部变量也称为内部变量。

局部变量是在函数内作定义说明的。

其作用域仅限于函数内,离开该函数后再使用这种变量是非法的。

例如:int f1(int a) /*函数f1*/{int b,c;……}a,b,c有效int f2(int x) /*函数f2*/{int y,z;……}x,y,z有效main(){int m,n;……}m,n有效在函数f1内定义了三个变量,a为形参,b,c为一般变量。

在f1的范围内a,b,c有效,或者说a,b,c变量的作用域限于f1内。

同理,x,y,z的作用域限于f2内。

m,n的作用域限于main函数内。

关于局部变量的作用域还要说明以下几点:1)主函数中定义的变量也只能在主函数中使用,不能在其它函数中使用。

同时,主函数中也不能使用其它函数中定义的变量。

因为主函数也是一个函数,它与其它函数是平行关系。

这一点是与其它语言不同的,应予以注意。

2)形参变量是属于被调函数的局部变量,实参变量是属于主调函数的局部变量。

3)允许在不同的函数中使用相同的变量名,它们代表不同的对象,分配不同的单元,互不干扰,也不会发生混淆。

如在前例中,形参和实参的变量名都为n,是完全允许的。

4)在复合语句中也可定义变量,其作用域只在复合语句范围内。

例如:main(){int s,a;……{int b;s=a+b;……/*b作用域*/}……/*s,a作用域*/}【例8.12】main(){int i=2,j=3,k;{int k=8;printf("%d\n",k);}printf("%d\n",k);}本程序在main中定义了i,j,k三个变量,其中k未赋初值。

c语言中各数据类型的存储空间长度

c语言中各数据类型的存储空间长度

C语言中各数据类型的存储空间长度1. 引言C语言是一种广泛应用的高级编程语言,它提供了丰富的数据类型用于存储和操作数据。

每个数据类型在内存中占用的存储空间长度是程序员需要了解的重要知识之一。

本文将详细介绍C语言中各数据类型的存储空间长度。

2. 基本数据类型C语言提供了几种基本数据类型,包括整型、浮点型和字符型。

下面是它们在内存中的存储空间长度:2.1 整型整型数据类型用于存储整数值。

C语言提供了不同长度的整型数据类型,包括char、short、int、long和long long。

它们在内存中的存储空间长度如下:•char:1字节•short:2字节•int:4字节•long:4字节•long long:8字节2.2 浮点型浮点型数据类型用于存储浮点数值。

C语言提供了两种浮点型数据类型,分别是float和double。

它们在内存中的存储空间长度如下:•float:4字节•double:8字节2.3 字符型字符型数据类型用于存储单个字符。

C语言提供了char数据类型来表示字符。

它在内存中的存储空间长度为1字节。

3. 限定符和修饰符除了基本数据类型外,C语言还提供了一些限定符和修饰符,用于扩展数据类型的表示范围和存储空间长度。

3.1 signed和unsignedsigned和unsigned限定符用于表示有符号和无符号的整型数据类型。

默认情况下,int类型是有符号的。

使用signed修饰符可以明确指定有符号的整型类型。

而使用unsigned修饰符可以明确指定无符号的整型类型。

3.2 short和longshort和long修饰符用于调整整型数据类型的存储空间长度。

short修饰符用于缩短整型数据类型的存储空间长度,而long修饰符用于扩展整型数据类型的存储空间长度。

3.3 long longlong long修饰符用于扩展整型数据类型的存储空间长度,它提供了更大范围的整数表示。

4. 枚举类型枚举类型用于定义一组具有离散值的常量。

c语言什么是变量_变量的分类

c语言什么是变量_变量的分类

c语言什么是变量_变量的分类大家在初学C语言的时候对各种变量之间的区别以及存储布局可能都有很多疑问,造成在使用变量的时候可能会遇到错误的地方。

下面是店铺为大家整理的关于c语言的介绍和分类,希望可以帮到大家哦。

c语言的变量特性:第一、变量定义要选择恰到好处的类型,变量的类型直接决定了它所存储的数据取值范围,这类似于我们生活中使用的各种容器,选择合适的变量类型,不但能保证数据存储安全,还能有效的节约系统资源;第二、变量的作用范围必须清楚,C语言最基本的功能单元是函数,在函数内部使用的变量是私有变量,只能在函数内部使用。

多个函数组成一个程序的功能模块,并安置在某一个C文件中,在这些函数的头部定义的变量是静态变量(局部变量),这种类型的变量模块内部的函数都可以访问。

如果在模块内部声明变量,并在该模块的头文件中导出,该类型变量就是全局变量,全局变量在整个工程中的所有函数都可以访问;第三、变量占用的RAM资源,私有变量是可以释放的,静态变量与全局变量是不可以释放的。

也就是说在程序运行的整个过程中,私有变量占用资源可以供不同的函数重复利用,而静态变量与全局变量是完全被占用不能重复利用的;第四、变量可以存放常数,但因为单片机RAM资源有限,强烈建议不要用变量存放常量,而是在资源相对丰富的Flash ROM中存放常量;第五、局部变量与全局变量对于函数来说,访问非常方便,但缺点显而易见:访问的函数越多,数据的安全性越低,一旦出现数据异常,很难排除问题。

所以,请尽量减少局部变量与全局变量的使用;第六、函数的型参个数尽量减少,这样型参只会占用通用寄存器组来完成参数传递工作。

如果参数过多,编译器可能会被迫分配占用RAM资源,这样不但参数传递效率变低,同时还会导致RAM资源浪费;c语言变量的分类全局变量的作用范围是整个程序(如果程序是多个文件,必须在其他的文件中说明)。

静态变量的作用范围要看静态变量的位置,如果在函数里,则作用范围就是这个函数。

c语言-位域在内存中的存放

c语言-位域在内存中的存放

c语⾔-位域在内存中的存放位域在内存中的存放位域在实际开发中可能⽤的⽐较少,但是对于理解内存存储数据⾮常有帮助!我们可以在结构体或共⽤体中描述⼀个简单的位域: ``` struct { char a:1; char b:1; char c:1; }st; ``` * ⾸先我们先说说这个结构体在内存中所占的⼤⼩ st变量占⽤了1个字节,但只有3位(bit)⽤来存储数据。

当然如果⽤的是int类型,将会占⽤4个字节,这是字节对齐的缘故。

*1字节(byte)=8位(bit),位是计算机中最⼩数据存储单位。

*数据是怎么存放的呢?在计算机中内存都会有内存地址,每个内存地址对应的是⼀个字节。

像指针和sizeof都是⽆法定位位域变量的,但是每个单位地址中的位也是有标记的。

我们可以把单位地址⽐作是门牌号,⽽这个门牌号对应的是数据的居住所,这个居住所有连续的8间房⼦,这些房⼦都只有⼀个出⼊⼝,且⼀次只允许⼀个数据(o或1)通过。

有了这些限定条件之后,就容易明⽩数据存放的规律。

我们可以把这⼋间房⼦标做0-7。

假设数据从左侧开始写⼊,那么⾸先写⼊的数据存放在最右侧,等到数据写⼊完,未写⼊的位补0。

据上所述,每个位都是有标记的,所以在读取位域时,可以准确读取指定位置的位。

*我们使⽤位域与共⽤体和结构体做个⼩例⼦来理解事先声明:由于计算机中有符号的整数都以补码形式存在,⽽不会出现像初期原码表⽰带符号的数字存在两个0(+0与-0),所以把原码中表⽰-0的数字来表⽰最⼤的负数。

也就是当只有符号位为1时,代表符号位的1也算到数字位中去了。

⼆进制10表⽰有符号位⼗进制-2、⼆进制1表⽰有符号⼗进制-1等等。

union{struct{char a:1;char b:1;char c:1;}st;char y;}un; //声明共⽤体变量名为unint main(){un.y = 1; //对共⽤体中的char类型进⾏赋值printf("%d %d %d\n",un.st.a,un.st.b,un.st.c); //对结构体中的值进⾏打印}结果:-1 0 0这个共⽤体的⼤⼩位为1字节,对un.y赋值为1,1转为⼆进制还是1,其他位补0,我们把数据在内存中的分布进⾏展⽰:可以看到除了序号为0的位是1,其他位都是0。

如何判断c语言的变量类型

如何判断c语言的变量类型

如何判断c语⾔的变量类型变量三要素:⼀个变量有三个基本的要素,变量的名称,变量的类型,变量的值。

所以int a = 10; 变量名为a,变量的存储类型为int型,变量的值为10。

变量还有⼀些属性如作⽤范围和存储类型。

变量作⽤范围和存储类型作⽤范围有局部变量和全局变量。

局部只在特定范围内起作⽤。

全部变量在整个程序运⾏期间起作⽤。

存储类型有auto(⾃动),static(静态),register(寄存器变量)⾃动变量auto默认省略,int a = 10; 和 auto int a = 10;是⼀样的。

⾃动变量动态的分配内存空间,数据存储在动态存储区内。

静态变量static,在函数初始化的时候就分配空间,⽽且数据存储在静态存储区内,在程序运⾏期间,变量的存储空间不会被释放掉。

指针变量指针变量除了上⾯的三要素以外,还有指针指向的数据类型。

int *p = &a;变量名为p,变量的类型为指针类型,变量的值为a的地址,该指针变量指向的数据类型为int类型。

如何判断变量类型int (*p)(int,int); 指向函数的指针。

是⼀个指针,该指针指向⼀个函数⼊⼝。

判断⽅法:p先和*结合,为⼀个指针。

后和(int,int)结合,指针指向返回值为int 的函数。

float *fun(int a); 返回指针值的函数。

为⼀个函数,形参为int型,返回值为⼀个float类型指针。

判断⽅法,fun和(int a)结合,为函数。

函数返回值为float类型指针。

int *p[4]; 指针数组。

为⼀个数组,数组⾥⾯元素的存储类型为指针类型。

判断⽅法:p和[4]结合,为⼀个数组,数组存储的类型为int类型指针。

float (*pointer)[4] ;指向⼀维数组的指针变量。

为⼀个指针,指针指向长度为4的数组。

判断⽅法:pointer和*结合,为⼀个指针。

该指针指向⼀个长度为4的,存有float类型的数组。

所以判断⼀个变量类型的时候,先看变量名的结合性,⾸先和什么结合就是什么类型变量,先和指针结合就是指针变量,和数组结合就是数组。

C语言中的数据类型选择指南

C语言中的数据类型选择指南

C语言中的数据类型选择指南在C语言中,数据类型是程序中存储数据的基本单位,它决定了变量在内存中所占据的空间大小和表示范围。

选择合适的数据类型可以提高程序的效率和可维护性。

在C语言中,数据类型可以分为基本数据类型、组合数据类型和空类型三种类型。

首先,我们来看一下C语言中的基本数据类型。

C语言中的基本数据类型分为整型、浮点型、字符型和布尔型。

整型数据类型用于存储整数,包括int、short、long等,其大小取决于机器架构和编译器实现。

浮点型数据类型用于存储实数,包括float和double,它们表示不同精度的浮点数。

字符型数据类型用于存储单个字符,包括char类型,它可以表示ASCII码字符。

布尔型数据类型用于存储逻辑值,包括_Bool和bool,用于表示真和假。

在选择整型数据类型时,需要考虑数据的取值范围和精度。

一般情况下,int类型已经可以满足大多数整数的存储需求,而short和long类型可以用来存储较小和较大的整数。

需要特别注意的是,不同机器上数据类型的大小可能不同,因此在跨平台开发时需要谨慎选择数据类型。

对于浮点型数据类型,一般情况下使用double类型即可满足大多数要求,因为它提供了较高的精度。

如果需要节省内存空间,可以选择float类型,但其精度较低。

在做科学计算或需要高精度的计算时,可能需要考虑使用long double类型。

字符型数据类型在C语言中主要用于表示单个字符,常用于处理文本数据。

对于字符型数据类型,一般情况下使用char类型即可,可以存储ASCII码字符。

需要注意的是,C语言中的字符类型是有符号的,如果需要无符号的字符类型,可以使用unsigned char类型。

布尔型数据类型用于表示逻辑值,一般存储真(true)或假(false)。

在C语言中,_Bool类型可以存储真和假,也可以使用标准库中的bool类型。

布尔型数据类型在条件判断和逻辑运算时非常有用,避免了使用0和1表示真和假的不便。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

首先要来理解一下可执行文件加载进内存后形成的进程在内存中的结构,如下图:
代码区:存放CPU执行的机器指令,代码区是可共享,并且是只读的。

数据区:存放已初始化的全局变量、静态变量(全局和局部)、常量数据。

BBS区:存放的是未初始化的全局变量和静态变量。

栈区:由编译器自动分配释放,存放函数的参数值、返回值和局部变量,在程序运行过程中实时分配和释放,栈区由操作系统自动管理,无须程序员手动管理。

堆区:堆是由malloc()函数分配的内存块,使用free()函数来释放内存,堆的申请释放工作由程序员控制,容易产生内存泄漏。

c语言中的存储类型有auto, extern, register, static 这四种,存储类型说明了该变量要在进程的哪一个段中分配内存空间,可以为变量分配内存存储空间的有数据区、BBS区、栈区、堆区。

下面来一一举例看一下这几个存储类型:
1. auto存储类型
auto只能用来标识局部变量的存储类型,对于局部变量,auto是默认的存储类型,不需要显示的指定。

因此,auto标识的变量存储在栈区中。

示例如下:
[cpp]view plaincopy
1#include <stdio.h>
2
3int main(void)
4{
5auto int i=1; //显示指定变量的存储类型
6int j=2;
7
8printf("i=%d\tj=%d\n",i,j);
9
10return 0;
11}
2. extern存储类型
extern用来声明在当前文件中引用在当前项目中的其它文件中定义的全局变量。

如果全局变量未被初始化,那么将被存在BBS区中,且在编译时,自动将其值赋值为0,如果已经被初始化,那么就被存在数据区中。

全局变量,不管是否被初始化,其生命周期都是整个程序运行过程中,为了节省内存空间,在当前文件中使用extern来声明其它文件中定义的全局变量时,就不会再为其分配内存空间。

示例如下:
[cpp]view plaincopy
12#include <stdio.h>
13
14int i=5; //定义全局变量,并初始化
15
16void test(void)
17{
18printf("in subfunction i=%d\n",i);
19}
[cpp]view plaincopy
20#include <stdio.h>
21
22extern i; //声明引用全局变量i
23
24int main(void)
25{
26printf("in main i=%d\n",i);
27test();
28return 0;
29}
[plain]view plaincopy
30$ gcc -o test test.c file.c #编译连接
31$ ./test #运行
[plain]view plaincopy
32结果:
33
34in main i=5
35in subfunction i=5
3. register存储类型
声明为register的变量在由内存调入到CPU寄存器后,则常驻在CPU的寄存器中,因此访问register变量将在很大程度上提高效率,因为省去了变量由内存调入到寄存器过程中的好几个指令周期。

如下示例:
[cpp]view plaincopy
36#include <stdio.h>
37
38int main(void)
39{
40register int i,sum=0;
41
42for(i=0;i<10;i++)
43sum=sum+1;
44
45printf("%d\n",sum);
46
47return 0;
48}
4. static存储类型
被声明为静态类型的变量,无论是全局的还是局部的,都存储在数据区中,其生命周期为整个程序,如果是静态局部变量,其作用域为一对{}内,如果是静态全局变量,其作用域为当前文件。

静态变量如果没有被初始化,则自动初始化为0。

静态变量只能够初始化一次。

示例如下:
[cpp]view plaincopy
49#include <stdio.h>
50
51int sum(int a)
52{
53auto int c=0;
54static int b=5;
55
56c++;
57b++;
58
59printf("a=%d,\tc=%d,\tb=%d\t",a,c,b);
60
61return (a+b+c);
62}
63
64int main()
65{
66int i;
67int a=2;
68for(i=0;i<5;i++)
69printf("sum(a)=%d\n",sum(a));
70return 0;
71}
[plain]view plaincopy
72$ gcc -o test test.c
73$ ./test
74a=2, c=1, b=6 sum(a)=9
75a=2, c=1, b=7 sum(a)=10
76a=2, c=1, b=8 sum(a)=11
77a=2, c=1, b=9 sum(a)=12
78a=2, c=1, b=10 sum(a)=13
6. 字符串常量
字符串常量存储在数据区中,其生存期为整个程序运行时间,但作用域为当前文件,示例如下:
[cpp]view plaincopy
79#include <stdio.h>
80
81char *a="hello";
82
83void test()
84{
85char *c="hello";
86
87if(a==c)
88printf("yes,a==c\n");
89else
90printf("no,a!=c\n");
91}
92
93int main()
94{
95char *b="hello";
96char *d="hello2";
97
98if(a==b)
99printf("yes,a==b\n");
100else
101printf("no,a!=b\n");
102
103test();
104
105if(a==d)
106printf("yes,a==d\n");
107else
108printf("no,a!=d\n");
109
110return 0;
111}
[plain]view plaincopy
112$ gcc -o test test.c
113$ ./test
114yes,a==b
115yes,a==c
116no,a!=d
总结如下表:。

相关文档
最新文档