一、字节和地址
为了更好地理解变量在内存中的存储细节,先来认识一下内存中的“字节”和“地址”。
1.计算机中的内存是以字节为单位的存储空间。内存的每一个字节都有一个唯一的编号,这个编号就称为地址。就好像酒店是以房间为单位的,每个房间都有一个唯一的房号,我们根据房号就能找到对应的房间。
里面的每个小框框就代表着内存中的一个字节,白色数字就是每个字节的地址(这里采取十六进制来显示,地址值是随便写的,仅作为参考,真实情况中的地址值不一定是这个),可以发现,内存中相邻字节的地址是连续的。
2.大家都知道,一个字节有8位,所能表示的数据范围是非常有限的,因此,范围较大的数据就要占用多个字节,也就是说,不同类型的数据所占用的字节数是不一样的。
二、变量的存储
1.变量类型的作用
跟其他编程语言一样,C语言中用变量来存储计算过程使用的值,任何变量都必须先定义类型再使用。为什么一定要先定义呢?因为变量的类型决定了变量占用的存储空间,所以定义变量类型,就是为了给该变量分配适当的存储空间,以便存放数据。比如char类型,它是用来存储一个字符的,一个字符的话只需要1个字节的存储空间,
因此系统就只会给char类型变量分配1个字节,没必要分配2个字节、3个字节乃至更多的存储空间。
2.变量占用多少存储空间
1> 一个变量所占用的存储空间,不仅跟变量类型有关,而且还跟编译器环境有关系。同一种类型的变量,在不同编译器环境下所占用的存储空间又是不一样的。我们都知道操作系统是有不同位数的,比如Win7有分32位、64位,编译器也是一样的,也有不同位数:16位、32位、64位(Mac系统下的clang编译器是64bit的)。由于我们是Mac系统下开发,就以64位编译器为标准。
2> 下面的表格描述了在64位编译器环境下,基本数据类型所占用的存储空间,了解这些细节,对以后学习指针和数组时是很有帮助的。
3> 下面的表格描述了在不同编译器环境下的存储空间占用情况
3.变量示例
当定义一个变量时,系统就会为这个变量分配一定的存储空间。
1 int main()
2 {
3 char a = 'A';
4
5 int b = 10;
6
7 return 0;
8 }
1> 在64bit编译器环境下,系统为变量a、b分别分配1个字节、4个字节的存储单元。也就是说:
- 变量b中的10是用4个字节来存储的,4个字节共32位,因此变量b在内存中的存储形式应该是0000 0000 0000 0000 0000 0000 0000 1010。
- 变量a中的'A'是用1个字节来存储的,1个字节共8位,变量a在内存中的存储形式是0100 0001,至于为什么'A'的二进制是这样呢,后面再讨论。
2> 上述变量a、b在内存中的存储情况大致如下表所示:
(注:"存储的内容"那一列的一个小格子就代表一个字节,"地址"那一列是指每个字节的地址)
- 从图中可以看出,变量b占用了内存地址从ffc1~ffc4的4个字节,变量a占用了内存地址为ffc5的1个字节。每个字节都有自己的地址,其实变量也有地址。变量存储单元的第一个字节的地址就是该变量的地址。变量a的地址是ffc5,变量b的地址是ffc1。
-
内存寻址是从大到小的,也就是说做什么事都会先从内存地址较大的字节开始,因此系统会优先分配地址值较大的字节给变量。由于是先定义变量a、后定义变量b,因此你会看到变量a的地址ffc5比变量b的地址ffc1大。
- 注意看表格中变量b存储的内容,变量b的二进制形式是:0000 0000 0000 0000 0000 0000 0000 1010。由于内存寻址是从大到小的,所以是从内存地址最大的字节开始存储数据,存放顺序是ffc4 -> ffc3 -> ffc2 -> ffc1,所以把前面的0000
0000都放在ffc2~ffc4中,最后面的八位0000 1010放在ffc1中。
4.查看变量的内存地址
在调试过程中,我们经常会采取打印的方式查看变量的地址
1 #include <stdio.h>
2
3 int main()
4 {
5 int a = 10;
6 printf("变量a的地址是:%p", &a);
7 return 0;
8 }
第6行中的&是一个地址运算符,&a表示取得变量a的地址。格式符%p是专门用来输出地址的。输出结果是:
这个0x7fff5fbff8f8就是变量a的内存地址
三、负数的二进制形式
1 int main()
2 {
3 int b = -10;
4 return 0;
5 }
在第3行定义了一个整型变量,它的值是-10。-10在内存中怎样存储的呢?其实任何数值在内存中都是以补码的形式存储的。
- 正数的补码与原码相同。比如9的原码和补码都是1001
- 负数的补码等于它正数的原码取反后再+1。(取反的意思就是0变1、1变0)
那么-10的补码计算过程如下:
1> 先算出10的二进制形式:0000 0000 0000 0000 0000 0000 0000 1010
2> 对10的二进制进行取反:1111 11111111
11111111 1111 1111 0101
3> 对取反后的结果+1:1111
11111111 11111111 1111 11110110
因此,整数-10在内存中的二进制形式是:1111
11111111 11111111 1111 11110110
四、变量的作用域
1.作用域简介
变量的作用域就是指变量的作用范围。先来看看下面的程序:
1 int main()
2 {
3 int a = 7;
4
5 return 0;
6 }
- 在第3行定义了一个变量a,当执行到这行代码时,系统就会为变量a分配存储空间
- 当main函数执行完毕,也就是执行完第5行代码了,变量a所占用的内存就会被系统自动回收
- 因此,变量a的作用范围是从定义它的那行开始,一直到它所在的大括号{}结束,也就是第3~6行,一旦离开这个范围,变量a就失效了
2.代码块
1> 代码块其实就是用大括号{}括住的一块代码。
1 int main()
2 {
3 {
4 int a = 10;
5
6 printf("a=%d", a);
7 }
8
9 a = 9;
10
11 return 0;
12 }
- 注意第3~7行的大括号,这就是一个代码块
- 当执行到第4行时,系统会分配内存给变量a
- 当代码块执行完毕,也就是执行完第6行代码后,变量a所占用的内存就会被系统回收
- 因此,变量a的作用范围是从定义它的那行开始,一直到它所在的大括号{}结束,也就是第4~7行,离开这个范围,变量a就失效了
- 所以,上面的程序是编译失败的,第9行代码是错误的,变量a在第7行的时候已经失效了,不可能在第9行使用
2> 如果是下面这种情况
1 int main()
2 {
3 int a = 9;
4
5 {
6 int a = 10;
7
8 printf("a=%d", a);
9 }
10
11 return 0;
12 }
- 注意第3、6行,各自定义了一个变量a,这种情况是没问题的。C语言规定:在不同作用域中允许有同名变量,系统会为它们分配不同的存储空间。
- 在第3行定义的变量a的作用域是:第3~12行;在第6行定义的变量a的作用域是:第6~9行。
- 最后注意第8行:尝试输出变量a的值。那这里输出的是哪一个变量a呢?先看输出结果:
这里采取的是“就近原则”,也就是第8行访问的是在第6行定义的变量a,并不是在第3行的变量a。
五、变量的初始化
变量在没有进行初始化之前,不要拿来使用,因为它里面存储的是一些垃圾数据
1 #include <stdio.h>
2
3 int main()
4 {
5 int c;
6
7 printf("%d", c);
8 return 0;
9 }
注意第5行的变量c,只是定义了变量,并没有给它赋初值。输出结果:
可以发现,变量c里面存储的是一些乱七八糟的数据
分享到:
相关推荐
不同类型的变量所占用的内存单元的大小不同,变量值随着变量赋值而改变。在程序运行过程中,通过对变量名来引用变量的值。 1-3 变量 变量定义格式: [存储类型] 数据类型 变量名1,变量名2,……; 例如: int x,y; /*...
C语言中的变量在内存中的存储情况探讨.pdf
接触过编程的人都知道,高级语言都能通过变量名来访问内存中的数据。那么这些变量在内存中是如何存放的呢?程序又是如何使用这些变量的呢?
C语言教程_C语言指针教程 包括指针的概念、指针变量、动态内存分配、多级指针等 资源为视频教程资源 希望对你的 C语言 学习有所帮助。
本篇文章是对在C语言中局部变量与全局变量在内存中的存放位置进行了详细的分析介绍,需要的朋友参考下
二、变量与指针的本质 1. 内存地址 2. 32位与64位系统 3. 变量 4. 指针变量 5. 操作指针变量 三、指针的几个相关概念 1. const属性 2. void型指针 3. 空指针和野指针 四、指向不同数据类型的指针 1. 数值...
1.3 变量、值和类型 1.4 表达式 1.5 语句 1.6 函数 1.7 小结 1.8 复习题 1.9 编程练习 第2章 C的数据类型 2.1 枚举类型 2.2 数据和内存 2.3 指针 2.4 数组 2.5 指针和数组 2.6 记录 ...
1、C中内存分为四个区 栈:用来存放函数的形参和函数内的局部变量。由编译器分配空间,在函数执行完后由编译器自动释放。 堆:用来存放由动态分配函数(如malloc)分配的空间。是由程序员自己手动分配的,并且必须...
在C语言中,变量是用来存储数据值的内存位置。在使用变量之前,需要先声明变量的类型和名称,例如: int num; // 声明一个整型变量num float price; // 声明一个浮点型变量price char letter; // 声明一个字符型...
C语言中局部变量和全局变量_等在内存中的存放位置
C语言里,变量存放在内存中,而内存其实就是一组有序字节组成的数组,每个字节有唯一的内存地址。CPU 通过内存寻址对存储在内存中的某个指定数据对象的地址进行定位。这里,数据对象是指存储在内存中的一个指定数据...
1-1 变量的地址与指针 计算机的内存是以字节为单位的一片连续的存储空间,每一个字节都有一个编号,这个编号就称为内存地址。内存的存储空间是连续的,内存的地址号也是连续的。一个变量实质上代表了“内存中的某个...
C语言不同变量内存区域(堆,栈,代码区,全局区,BSS段)
C语言的全局变量和静态变量有何区别? 答案:全局变量在整个程序中都有效,而静态变量只在声明它的文件有效。 如何在C语言中申请动态内存? 答案:可以使用malloc()函数或calloc()函数申请动态内存。
以下是一些常见的C语言面试题,这些问题覆盖了基本语法、指针、内存管理、数据结构等多个方面: 1. **基础语法** - C语言中的基本数据类型有哪些? - `#include <filename.h>` 和 `#include "filename.h"` 有什么...
c语言变量 变量其实只不过是程序可操作的存储区的名称。C 中每个变量都有特定的类型,类型决定了变量存储的大小和布局,该范围内的值都可以存储在内存中,运算符可应用于变量上。 什么是常量,变量你懂了吗? 作者...
在C语言里,数据类型即说明了它是什么类型的数据,更重要的是存储这类数据所需的内存的大小,C语言允许使用的类型如下:在基本类型中的整数类型、浮点数类型和字符类型都已经在之前的文章中使用过了,这里面的_Bool...
c语言开发中,最常见的问题分析,如果把这部分好好分析一遍,我相信你一定会有所提升的
在C语言中,变量是对程序中数据所占用内存空间的一种抽象,定义变量时,用户定义变量的名,变量的类型,这是变量的操作属性。不仅可以通过变量名访问该变量,系统还通过该标识符确定该变量在内存空间的位置。在...