c语言变量名和地址的关系

在汇编编译器编译时直接将变量名转换成内存地址,变量名并不占内存空间

  • 在编译的时候编译器会把程序中出现的所有变量名都换成相对内存地址,变量名不占内存
  • 变量名不占空间

    变量:用来标识(identify)一块内存区域,这块区域的值一般是可以更改的,这就是它“变”的由来,但是我们可以通过使用如const等一些修饰符号来限定这一内存区域的操作特性(characteristic),即变量的操作特性。用const修饰的使变量不能更改的就和常量一样的变量叫做常变量。

    变量名:是一个标识符(identifier),用来指代一块内存区域,即变量,使用变量使我们操作内存以区域(area),以块(block)为单位,提高了方便性。

    你的机器代码中,是不会出现变量名的;变量名是给我们程序员操作内存来使用的。

    想想在汇编年代,没有变量名,我们操作内存,都是用地址来直接操作的,还要控制区域大小;当然汇编语言已经有了简单的变量。

    对于编译器,它会搜集我们的变量名,比如我们定义了一个全局的int a;那么编译器都为我们做了什么呢?

    它会为程序预留4个字节的空间(假设在32位平台),并把我们的变量名“a”保存进符号表,并用这个符号表的索引对应实际的空间。

    如果下面出现b = a;那么它就会根据符号表找到变量的真正的物理位置,取得它的值,赋给b。

    这是写编译器需要做的,我们需要建立符号表。

    但是实际在汇编层次上,操作的都是地址而已,不存在任何名称了。

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    除了变量名不是内存地址,其他名都是地址。对么?

    所谓的其他名无非是函数名、标识符常量名、指针名、数组名、结构名、类名等等。

    楼主的话有部分是对的, 比如指针名、数组名、函数名就是地址,它们分别表示指针所指向元素的地址、数组的首地址和函数的入口地址。

    变量名虽然不直接表示地址,但可用取地址符号&来获得它所代表的变量的存放地址。因为在定义变量的同时会分配给它相应的空间。

    但类和结构只有事例化时才为它分配空间,从而不能用取地址符号&来获得类名或结构名的地址。

    变量名是用来标识某个内存块的

    地址就是地址啦,如是变量名的话,用取地址运算符&就可以得到它标识的内存块的地址,

    而指针变量呢,它本身也是一个变量名,只不过它标识的那块内存存放的是一个地址值

    变量是地址的别名..就像刚生的小孩,你只知道他在地球上的某个位置,而不能叫出他名字,给你取个名

    ~~~~~~~~~~~~~~~~~~~~~~~

    定义int a;时,编译器分配4个字节内存,并命名该4个字节的空间名字为a(即变量名),当用到变量名a时,就是在使用那4个字节的内存空间.

    5是一个常数,在程序编译时存放在代码的常量区存放着它的值(就是5),当执行a=5时,程序将5这个常量拷贝到a所在的4个字节空间中,就完成了赋值操作.

    a是我们对那个整形变量的4个字节取的”名字”,

    是我们人为给的,实际上计算机并不存储a这个名字,只是我们编程时给那4个字节内存取个名字好用.实际上程序在编译时,所有的a都转换为了那个地址空间了.编译成机器代码后,没有a这个说法了.a这个名字只存在于我们编写的代码中.

    5不是被随机分配的,而总是位于程序的数据段中,可能在不同的机器上在数据段中的位置可能不一致,它的地址其实不能以我们常用到的内存地址来理解,因为牵扯到一个叫”计算机寻址方式”的问题,所以写很多都解释不清楚,你自己找本汇编语言的书来学一下吧………

    ~~~~~~~~~~~~~~~~~~~~~~~~

    C语言中变量只是标识对应存储单元内的存储内容。与地址的对应关系

    int a=3;

    a—&a

    一一对应啊,变量名只是一个便于记忆识别的名称,编译器会将他编译成相应的内存地址的.

    变量都要占据一定的内存。

    通过定义该变量的指针, [类型]* 指针名=你要指向的变量名

    那么该指针中存储的就是你的变量的内存地址。

    &你的变量名 这样就可以直接获取到你的变量地址

    或者定义引用 [类型]& 引用名=变量名

    该引用可通过变量的地址来对变量进行修改

    ~~~~~~~~~~~~~~~~~~~~~~~~~

    变量名是给编译器看的,编译器根据变量是局部还是全局分配内存地址或栈空间,所谓的变量名在内存中不存在,操作时转换成地址数存放在寄存器中了。

    编译器会将合法的变量名放到一个叫“符号表”的一个表中。

    每个符号对应一个地址。当你调用此变量时,就会根据此符号表找到对应的地址,然后进行操作。

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    还没有运行怎么会占用内存呢?!(这一点还要怀疑吗!?)

    所谓在编译期间分配空间指的是静态分配空间(相对于用new动态申请空间),如全局变量或静态变量(包括一些复杂类型的常量),它们所需要的空间大小可以明确计算出来,并且不会再改变,因此它们可以直接存放在可执行文件的特定的节里(而且包含初始化的值),程序运行时也是直接将这个节加载到特定的段中,不必在程序运行期间用额外的代码来产生这些变量。

    其实在运行期间再看“变量”这个概念就不再具备编译期间那么多的属性了(诸如名称,类型,作用域,生存期等等),对应的只是一块内存(只有首址和大小),所以在运行期间动态申请的空间,是需要额外的代码维护,以确保不同变量不会混用内存。比如写new表示有一块内存已经被占用了,其它变量就不能再用它了; 写delete表示这块内存自由了,可以被其它变量使用了。(通常我们都是通过变量来使用内存的,就编码而言变量是给内存块起了个名字,用以区分彼此)

    内存申请和释放时机很重要,过早会丢失数据,过迟会耗费内存。特定情况下编译器可以帮我们完成这项复杂的工作(增加额外的代码维护内存空间,实现申请和释放)。从这个意义上讲,局部自动变量也是由编译器负责分配空间的。进一步讲,内存管理用到了我们常常挂在嘴边的堆和栈这两种数据结构。

    最后对于“编译器分配空间”这种不严谨的说法,你可以理解成编译期间它为你规划好了这些变量的内存使用方案,这个方案写到可执行文件里面了(该文件中包含若干并非出自你大脑衍生的代码),直到程序运行时才真正拿出来执行!

    ~~~~~~~~~~~~~~

---------------------

本文来自 csdn_walter 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/CSDN_LSD/article/details/78572491?utm_source=copy

原文地址:https://www.cnblogs.com/gsx-600r/p/9742244.html

时间: 2024-10-09 20:40:14

c语言变量名和地址的关系的相关文章

C语言变量名转字符串的方法

C语言中将变量名转换成字符串使用的是#符号,来看下边两个宏定义: #define name2str(name) (#name) #define print_val(x) printf(#x" = %d\n", x) 使用的时候自动将相应的变量名转换成字符串,示例代码: int main() { int a = 10; short b = 11; char c = 12; void *addr = (void *)123456; int xyz = 100; printf("w

C语言中与指针相关问题——论数组名和数组名取地址的关系

这是由一道面试题联想到的一些问题,这里自己给做个小总结! 首先看看这道面试题: #include <stdio.h> int main() { int a[5] = { 1, 2, 3, 4, 5 }; int *pi = &a + 1; printf("%d, %d\n", *(a + 1), *(pi - 1)); return 0; } 答案是2, 5.至于是为什么,我后面说一下我自己的理解. 这里有个要注意的地方,以上代码在CodeBlock中会有个警告,但

[C语言]判断C语言变量名是否合法

Code: 1 #include <stdio.h> 2 #include <string.h> 3 int main() 4 { 5 int n,i; 6 scanf("%d",&n); 7 while(n--){ 8 char a[50]; 9 gets(a); 10 if((a[0]>='a'&&a[0]<='z')||(a[0]>='A'&&a[0]<='Z')||a[0]=='_'){ 1

C语言中变量名及函数名的命名规则与驼峰命名法

一.C语言变量名的命名规则:(可以字母,数字,下划线混合使用) 1. 只能以字母或下划线开始:2. 不能以数字开始:3. 一般小写:4. 关键字不允许用(eg:int float=2//error  float 为保留字不允许用): 二.函数名的命名规则 1.见名知意:2.自定义函数函数名首字母大写(库函数里的函数名都是以小写字母定义,为了区分库函数和自定义函数,避免冲突). 三.宏定义里面的变量 全大写 eg:#define SIZE 100(后面函数所有出现的SIZE全用100代替,它在所有

区块链基础语言(七)——Go语言变量

一.变量名 1.1 命名规则 为提升代码可读性和可维护性,多采用统一的.可读性高的命名方式.Go语言变量名由一个或多个字母.数字.下划线组成的序列,但第一个字符必须是字母或下划线,不能是数字,且区分大小写.例如:1a不能作为变量名,myname和myName是不同的变量名. 1.2 命名风格 命名风格有多种,常见的有驼峰式命名和下划线命名,而Go语言拥护驼峰命名法,排斥下划线法.驼峰命名法分为两种: ? 大驼峰式命名:用大写字母分隔语义,首写字母大写,例如HelloWorld: ? 小驼峰式命名

go语言变量

变量可以通过变量名访问 Go 语言变量名由字母.数字.下划线组成,其中首个字符不能为数字 声明变量的一般形式是使用 var 关键字: var identifier type 变量声明 1. 指定变量类型,如果没有初始化,则变量默认为零值. var v_name v_type v_name=name 零值就是变量没有做初始化时系统默认设置的值. 数值类型: 0 布尔类型为:false 字符串为 ""(空字符串) 2.根据值自行判定变量类型 var v_name=name 3. 多变量声明

★【C语言及程序设计】异名同地址的变量

多个异名同地址的变量,用指针仅操作其中一个会引起其它所有变量的改变. 例如下面代码的第10行. #include "stdafx.h" void fun(int *a, int *b, int *c) { int *temp; temp = a; // a-&a-5, b-&b-7, c-&c-3, t-&a-5 a = b; // a-&b-7, b-&b-7, c-&c-3, t-&a-5 b = temp; // a

C语言 对数组名取地址

作者 : 卿笃军 你有没有想过,对一个一维数组名取地址,然后用这个地址进行加减运算.这会出现什么样的结果呢? 示例: int a[5] = {1,2,3,4,5}; int *p = (int *)(&a+1); printf("%d\n",*(p-1)); 这个输出会是多少呢? 咦?为什么第二行需要强制转化类型呢? 答:a是一个一维数组的名字,&a相当于一个指向一维数组的指针.怎么感觉这么熟悉?指向数组的指针,那不就是行指针吗?int (*p)[]. 行指针+1,就是

C语言的数组名和对数组名取地址

http://blog.csdn.net/zdcsky123/article/details/6517811 相信不少的C语言初学者都知道,数组名相当于指针,指向数组的首地址,而函数名相当于函数指针,指向函数的入口地址.现在又这样一个问题,如果对数组名取地址,那得到的会是什么呢?很多人立刻会想到:给指针取地址,就是指针的指针,既二级指针嘛!当然这样的结论是错误的,不然这篇笔记也就没有意义了. 下面我们来逐步分析,下面是一段验证这个问题的代码 Code: #include<stdio.h> in