int a = 10; 中的a到底是个什么玩意

chichenzhe 2014-07-30 05:01:35
RT
1. a是什么,存在哪(不是10放在哪,而是a在哪)
2. 我们在程序里使用 b = a; 就能唤出a指向的实际值10, 这个时候唤出a我们只用了一个a字符标记. 但是在机器层面, 这个a等同于什么
3. 接2, a是否就是一个 地址值,指向了常量区的10还是变量区的10 ?

4. 从变量本质上讲, 是否所有变量的行为都是 地址代号? 或者可以广义的把所有变量都理解为指针,而只不过真正的指针又更特殊一些?
...全文
1285 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
d1070193993 2014-07-31
  • 打赏
  • 举报
回复
这种小问题其实也不用磕磕碰碰了...知道个意思就可以咯
chichenzhe 2014-07-31
  • 打赏
  • 举报
回复
非常感谢大家的回帖. 我已经有所收获. 感谢.
moonwrite 2014-07-31
  • 打赏
  • 举报
回复
指针决定操作的位置,类型决定操作的长度(也就是要操作多少个bit),和这个长度的意义 long l = 97; (指针指向内存中的某位置,要操作64bit) int i=(int)l; (指针指向内存中的某位置,要操作32bit) char c = (char)i; //c = a!!!!!!!!这是很有趣的 内存中只是一大堆1和0~ 我们要给这些1和0赋予意义 所以逻辑 太极八卦图由阴和阳两个最基本的组成 8卦图每个卦的长度是3 64卦图每个长度是6 要表达更多的意思需要更多的长度, 同时我们还要规定编码规则, 如我们可以规定101为 + 也可以规定101 为 a 存进去的规定和取出来的规定一致最好,不一致也无所谓
mjp1234airen4385 2014-07-31
  • 打赏
  • 举报
回复
这个大学没学过么,还是忘记了? 突然开始纠结这些了。
欢乐的小猪 2014-07-31
  • 打赏
  • 举报
回复
a 是变量名
ninteo 2014-07-31
  • 打赏
  • 举报
回复
这个应该跟你放在程序里的什么位置有关吧,你把它当全局变量它就是放在程序的数据段里的,汇编里应该是用.global声明的,你要是放在函数里,那它就是在程序堆栈段里面的,不管放在什么地方在程序执行的时候,根据生成的汇编代码这个值会随时取出来放到寄存器里。你可以用gcc生成汇编代码,然后把变量放到不同位置看一下就知道了
老李家的小二 2014-07-31
  • 打赏
  • 举报
回复
建议看一下值类型与引用类型的差异
haibo521333 2014-07-31
  • 打赏
  • 举报
回复
int a =10;
内存图,举例而已:
0 _________________............._________128
|_|_|_|_|_|_|_|_|_|_|_|_|............|_|_|_|_|_|_|_|
|----a----|
/10在里边\
於黾 2014-07-31
  • 打赏
  • 举报
回复
引用 15 楼 chichenzhe 的回复:
还是接我2楼的问题. char* pc = "c123"; string str = "c123"; 我这么理解: 1.pc 先会被翻译成 地址码: 1000002 我们写代码写的是pc 而机器自己翻译的叫做 1000002 的编号. 2.这个时候 我们说的变量名为 pc 机器自己说的变量名叫1000002 3.而后 1000002 指向了一个内存的值. 由于这是个指针变量. 所以这个值必然也是个数字. 4.但是我们拿到这个值之后并没完. 他还有下一步的用途. 这个值也是个地址. 他指向了 c123/0 的 开头地址. 所以pc是个地址. 这个地址指向一个值. 而这个值同时也是一个地址. 最终指向了一个最后要操作的地方. 而 str先会被翻译成 地址码: 1000008 和 2000008 1,2,3步骤和pc都是雷同的. 只不过pc有第4步骤而str没有. 只不过pc只指向了1个值, 而str指向了2个值, 1000008指向了2个字节的short. 2000008指向了c123.... 的开头地址. 但这个c123和上面的c123分别在内存堆,栈的不同地方. 2个字节的short为这个变量标识了最终他有资格读取和篡改的字符数有多少个. 其实我还有个疑惑. 一个地址码只能指向一个内存的最小区域(byte) 那么一int32却需要4个字节来表达. 那么一个地址码总不能同时指向4个byte吧, 他再怎么指,也只能指第1个起始byte的地方. 是否这个原理的控制 是要分地址码区间的呢? 比如 300008 ;3开头的地址码总是指int32的. 这样机器就可以凭借仅仅知道开头地址而能正确读取接下来的数据 --------------------- 我的这些理解型认识 书本上能找到么? 我粗翻了下编译原理, 大篇幅的语义解释和词法分析呀. 这些我暂时不需要了解......
指针需要知道自己指向的变量类型,否则它不知道该如何访问被指向的数据 这个类型在内部仅仅是个枚举值,所以是同样的指针被标明不同的用途.当然你也可以理解为不同类型的指针 变量是有属性的,string的长度就是它的属性.当然类型也可以看成一个属性. 这个属性在构造的时候就会指明,否则内存里不过是一堆二进制数,没有属性,机器怎么知道里面数据到底多长,你又想怎么用?
谁学逆向工程 2014-07-31
  • 打赏
  • 举报
回复
这个得用汇编语言来解释,西井语言不行。int a中的a其实就是个内存区
gangAndgang 2014-07-31
  • 打赏
  • 举报
回复
这个概念在C#中可能不太好理解,但在C/C++中就比较好理解了。 C/C++中有自动变量与指针变量的区别,即 int a = 10; //自动变量 int *a = new xxxx / malloc(xxx), *a = 10; //这是指针变量 二者的区别在存储方面主要在于自动变量位于栈上,指针变量在堆中。但对于编译器而言,其实都当作指针在处理,只是这个指针计算实际地址时算法不一样。
weiyulin510037 2014-07-30
  • 打赏
  • 举报
回复
看似简单的问题,结果不简单
chichenzhe 2014-07-30
  • 打赏
  • 举报
回复
还是接我2楼的问题. char* pc = "c123"; string str = "c123"; 我这么理解: 1.pc 先会被翻译成 地址码: 1000002 我们写代码写的是pc 而机器自己翻译的叫做 1000002 的编号. 2.这个时候 我们说的变量名为 pc 机器自己说的变量名叫1000002 3.而后 1000002 指向了一个内存的值. 由于这是个指针变量. 所以这个值必然也是个数字. 4.但是我们拿到这个值之后并没完. 他还有下一步的用途. 这个值也是个地址. 他指向了 c123/0 的 开头地址. 所以pc是个地址. 这个地址指向一个值. 而这个值同时也是一个地址. 最终指向了一个最后要操作的地方. 而 str先会被翻译成 地址码: 1000008 和 2000008 1,2,3步骤和pc都是雷同的. 只不过pc有第4步骤而str没有. 只不过pc只指向了1个值, 而str指向了2个值, 1000008指向了2个字节的short. 2000008指向了c123.... 的开头地址. 但这个c123和上面的c123分别在内存堆,栈的不同地方. 2个字节的short为这个变量标识了最终他有资格读取和篡改的字符数有多少个. 其实我还有个疑惑. 一个地址码只能指向一个内存的最小区域(byte) 那么一int32却需要4个字节来表达. 那么一个地址码总不能同时指向4个byte吧, 他再怎么指,也只能指第1个起始byte的地方. 是否这个原理的控制 是要分地址码区间的呢? 比如 300008 ;3开头的地址码总是指int32的. 这样机器就可以凭借仅仅知道开头地址而能正确读取接下来的数据 --------------------- 我的这些理解型认识 书本上能找到么? 我粗翻了下编译原理, 大篇幅的语义解释和词法分析呀. 这些我暂时不需要了解......
chichenzhe 2014-07-30
  • 打赏
  • 举报
回复
引用 9 楼 caozhy 的回复:
.... 那么问题就简单了。你去看一个机器程序,或者反汇编出来的程序,你能看到“变量”和“指针”是什么么?你只能看到一条条指令一会儿写入这个内存,一会儿从那个地址读出来,一会儿将这个数字放入寄存器,一会儿从那个寄存器取出来,等等。既然如此,哪里来的变量。 ....
我个人认为是有变量的. 只不过我们写代码的时候他叫做a. 而机器自己翻译的时候,他被译作 1个数. 而后机器可以用这个数来分清楚谁是谁. 而我们自己则用感性思维的 a/ num/ count/i / strMessage 等东西来区分谁是谁. 虽然你给的2段代码可能最终都只生成一段汇编. 但是这不能证明汇编之外,他没有对这2段代码的 变量名 做额外的手脚. 否则我觉得程序世界就要乱套了. 根据你给我的blog: http://blog.csdn.net/koself/article/details/7912351 张三和李四还是得要能区分的. 不是么.
chichenzhe 2014-07-30
  • 打赏
  • 举报
回复
引用 4 楼 caozhy 的回复:
编译器对待一个变量,可能会放入内存,可能会放入寄存器,甚至可能优化掉。 任何一本编译原理的书上都会有详细的介绍。 我随便找篇网文:http://blog.csdn.net/koself/article/details/7912355 更完整的自己看书去。
我有本找人借的编译原理. 我本身大学是计算机通信, 那会我们系没有编译原理这课. 你给的url不错. 谢谢.
moonwrite 2014-07-30
  • 打赏
  • 举报
回复
引用 6 楼 caozhy 的回复:
反正你理解:变量名是给编译器看的,编译器根据变量是局部还是全局分配内存地址或栈空间,所谓的变量名在内存中不存在,操作时转换成地址数存放在寄存器中了。其实可以理解为是符号表起到了连接作用。就可以了。 好的编译器,会尽可能将局部变量优化在寄存器上面——寄存器哪里来的指针?
栈空间空间也是内存上的一段,只是因为它的目的所以给它起了一个逻辑概念~栈 寄存器 是cpu内部的~ cpu对外的接口就只有地址总线,所以我把地址总线,所以我就想象成指针。 没有任何数据或指令一开始就去到cpu内部的寄存器~必须经过地址总线~这个我是可以肯定的。 地址总线找到内存中的某位置~加载数据~然后cpu内的寄存器怎么操作这些数据~暂时不说
引用 8 楼 caozhy 的回复:
[quote=引用 1 楼 moonwrite 的回复:] 把10存放在内存位置为a的地方上
这种说法从第一句就错了。(当然,我是说编译型语言,比如C++ C#) 编译器编译的过程就是把源代码转化成机器代码的过程(C#可以理解是转化成一种抽象机器的指令),所以在这个过程中不存在什么把变量放在什么内存上。[/quote] 那么问题就简单了。你去看一个机器程序,或者反汇编出来的程序,你能看到“变量”和“指针”是什么么?你只能看到一条条指令一会儿写入这个内存,一会儿从那个地址读出来,一会儿将这个数字放入寄存器,一会儿从那个寄存器取出来,等等。既然如此,哪里来的变量。 比如如下指令: mov eax, 10 //把10放存进寄存器eax,但这个10是从哪里,就是反编译出现了10,我也认为是这个反编译工具对内存推算的结果。不可能凭空出现10。因为mov eax, 10 已经是cpu内部的了~,因为cpu的寄存器就只有那么几个~所以他不能存放所有变量,必须把一些计算结果存放回内存~所以...算了~突然去搜索一下~看到百度百科 寄存器是中央处理器内的组成部分。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令数据地址。 add eax, 20 mov ptr[100], eax mov eax, 30 inc eax mov ptr[101], eax 因为我们都是用高级语言的~ 而且在机器层面就只有 一会儿写入这个内存,一会儿从那个地址读出来,一会儿将这个数字放入寄存器,一会儿从那个寄存器取出来, 所以我们需要建立更多的逻辑概念来从高层映射到底层 或者从底层映射到高层。 另外我说的变量是由基址+偏移来的~ 这个只是我以前搞游戏外挂的时候发现人物血量的地址每次加载游戏后都是不一样的 所以猜想的~ 当然指针也可能由基址+偏移而来。 另外从C#的反射来看~ 现在的语言+编译器更喜欢将变量名也编译到内存中去~不然我们也反射不了~
yaotomo 2014-07-30
  • 打赏
  • 举报
回复
学习了
phommy 2014-07-30
  • 打赏
  • 举报
回复
int a = 10 如果出现在方法里,几乎一定是一个栈上的变量,只在传说中看到过把它放到寄存器里。 如果没出现在方法里,也就是某个类的成员变量,它会指向堆上的一个32位地址,具体来说就是这个类的实例的内存地址+变量i在该类里的位置偏移量 还有一个特殊情况,如果出现在方法里、但它被闭包使用了,就会是一个自动生成类的实例的成员变量,也是指向堆上的一个地址 另两个传说是,如果它没有被使用会被优化掉;如果它没被赋值会被inline,我并没有亲见
threenewbee 2014-07-30
  • 打赏
  • 举报
回复
我很小的时候,家里很穷,那时候我妈妈编写单片机程序都是画好框图手工转化成机器码的。后来我家买了一台386,她之后写程序才用汇编器转换。

我想说的是,手工产生代码和用程序产生,本质上是一样的,理论上说,如果人掌握了编译器全部的转换规则(单片机的指令足够简单,这一点显得更明显),你不能从最终的程序区分它是手工转换出来的代码还是编译器产生的代码。

那么问题就简单了。你去看一个机器程序,或者反汇编出来的程序,你能看到“变量”和“指针”是什么么?你只能看到一条条指令一会儿写入这个内存,一会儿从那个地址读出来,一会儿将这个数字放入寄存器,一会儿从那个寄存器取出来,等等。既然如此,哪里来的变量。

比如如下指令:
mov eax, 10
add eax, 20
mov ptr[100], eax
mov eax, 30
inc eax
mov ptr[101], eax

你根本看不出这段代码来自
int a = 10;
int x = a + 20;
int b = 30;
int y = b++;
还是
int a = 10;
int x = a + 20;
int a = 30;
int y = a++;

(如果a在程序后面不再使用的话,对如上代码产生如上的机器码都是允许的)
你可以说eax就是变量a么?如果你非要这么说,那么也只有前3行代码勉强可以算。
threenewbee 2014-07-30
  • 打赏
  • 举报
回复
引用 1 楼 moonwrite 的回复:
把10存放在内存位置为a的地方上
这种说法从第一句就错了。(当然,我是说编译型语言,比如C++ C#) 编译器编译的过程就是把源代码转化成机器代码的过程(C#可以理解是转化成一种抽象机器的指令),所以在这个过程中不存在什么把变量放在什么内存上。
加载更多回复(7)

110,539

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧