标题:关于const一问
只看楼主
天使梦魔
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:37
帖 子:564
专家分:2754
注 册:2007-8-29
得分:0 
&a为引用,一般和指针配套使用.
引用一般给出的是地址.
int a;//那么&a就是变量a的内存地址,比如0x123456
int *b=&a;//指针只能指向地址,那么a的地址就给以了指针b
这样只要操作b就可以对a进行改变.指针是一段没有实际内存空间可以存数据的东西.
2008-01-27 10:45
eagleboycn
Rank: 1
等 级:新手上路
帖 子:191
专家分:0
注 册:2007-9-26
得分:0 
[bo]以下是引用 [un]eagleboycn[/un] 在 2008-1-26 22:18 的发言:[/bo]

.......................
在编译时候const变量象#define的一样被值替代
而只有非const变量才存在于数据区?
.........对&a又怎么理解?


LS:你可能误会了,我是说在"在编译时候const变量象#define的一样被值替代,而只有非const变量才存在于数据区?"
此时,已有定义const int a,然后对a取地址是怎么做的?具体的原理

兵法的精要在于韬晦自己
2008-01-27 17:12
天使梦魔
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:37
帖 子:564
专家分:2754
注 册:2007-8-29
得分:0 
这个和程序原理差不多.
一个程序被系统加载后,在内存内分布了很多个区,其中有专门存放代码的区,和专门存放数据的区.
程序运行时从存放代码的地方开始,然后分别到各个区一步步处理.
不管是const还是#define系统见到这2个声明后都要为其分配数据区的地址(#define是C中的静态修饰符,用一般的语句得不到地址.一般的书籍在提示的时候,在C++中能用const就用)

这样我们得到一个信息,编程语句最终要通过编译器的检查.
如果在程序中声名一个:
const int i=0;
i=1;//错误,编译器不让通过
但指针却能通过,因为指针指向的是数据区地址,而不是代码区的内容.
那在程序编译好后:
int *s=&i;//处理时直接跳到数据区,不经过代码区(它是地址,不是变量名)
cout<<i;//经过代码区时看到const修饰符,跳过数据区

[[it] 本帖最后由 天使梦魔 于 2008-1-28 13:23 编辑 [/it]]
2008-01-28 13:21
eagleboycn
Rank: 1
等 级:新手上路
帖 子:191
专家分:0
注 册:2007-9-26
得分:0 
[bo]以下是引用 [un]天使梦魔[/un] 在 2008-1-28 13:21 的发言:[/bo]

......不管是const还是#define系统见到这2个声明后都要为其分配数据区的地址(#define是C中的静态修饰符,用一般的语句得不到地址.
但指针却能通过,因为指针指向的是数据区地址,而不是代码区的内容.
那在程序编译好后:
int *s=&i;//处理时直接跳到数据区,不经过代码区(它是地址,不是变量名)
cout<<i;//经过代码区时看到const修饰符,跳过数据区

谢谢...................................................
是不是可以这么理解:
只要遇到const 变量,由编译器跳转代码区查找,屏蔽数据区
而该变量的指针或者引用操作时却直接跳转数据区查找?
类似于"多态性"?指针的静态类型与动态类型不同?

[[it] 本帖最后由 eagleboycn 于 2008-1-29 07:53 编辑 [/it]]

兵法的精要在于韬晦自己
2008-01-28 17:57
eagleboycn
Rank: 1
等 级:新手上路
帖 子:191
专家分:0
注 册:2007-9-26
得分:0 
另外,我看有些书上面说,对基本类型const变量一般并不分配数据区地址,只有在要用到指针或者引用时候才分配地址,是这样的吗?
那么对const int a而言
&a=={int *p=new int;*p=a;}?

兵法的精要在于韬晦自己
2008-01-28 18:02
天使梦魔
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:37
帖 子:564
专家分:2754
注 册:2007-8-29
得分:0 
算不上类型不同.
你理解引用的时候不要把它理解成变量名.
int a;
先看下这个a在内存中的做法,内存中要为a分配4个数据段.如:
0x000001,0x000002,0x000003,0x000004
那么,&a就等于0x000001
指针只能指向地址,如果用int *i=a 那就错了.a是变量的名字不是一段地址.
从程序的角度,当遇到一个变量名的时候,会从代码区找到它所在的数据区的地址,以便来工作.(系统→变量名→是否为const,是的话不去找地址→查找变量名对应的地址→修改,或者直接返回代码区被定义过的值)
但指针就不用了,指针告诉它这里是数据区的一段地址.(系统→指针→得到指针地址→修改)

说白了,指针危险也就危险在这.它甚至可以指向代码区的地址,系统不在乎是否对错.直接修改你的值.
int a,b;
//a的地址是 0x000001,0x000002,0x000003,0x000004 的这段
//b的地址是 0x000005,0x000006,0x000007,0x000008 的这段
int *i=0x000003;
问题来了,这个是整型指针,系统同样要默认为其分配4个地址,但地址却在2个变量的中间,一但i被给值,2个变量的值都被改变.
-------------------------------------------------------------------
对于第二个问题,的确是自分配,但算不上new关键字.
它那段地址的变量名默认改成a了(被编译成汇编时,被一段标志取代)
这个已经没有什么意义.反正空间已经被占.又不能通过a来改值,指针又不需要变量名.可以说这段标志没有用了.
收到的鲜花
  • eagleboycn2008-01-29 16:34 送鲜花  2朵   附言:谢谢!
2008-01-29 11:17
eagleboycn
Rank: 1
等 级:新手上路
帖 子:191
专家分:0
注 册:2007-9-26
得分:0 
[bo]以下是引用 [un]天使梦魔[/un] 在 2008-1-29 11:17 的发言:[/bo]

算不上类型不同.
你理解引用的时候不要把它理解成变量名.
int a;
先看下这个a在内存中的做法,内存中要为a分配4个数据段.如:
0x000001,0x000002,0x000003,0x000004
那么,&a就等于0x000001
指针只能指向地址,如果用int ...


Thank you so much!!!
那么是不是可以这么理解:const 变量于其他变量区别在于在编译阶段由代码(保证没有对const的重赋值)保证值的唯一,
以后则由对指针(引用)的"忽略(屏蔽)"保证?

兵法的精要在于韬晦自己
2008-01-29 16:48
leeco
Rank: 4
等 级:贵宾
威 望:10
帖 子:1026
专家分:177
注 册:2007-5-10
得分:0 
没什么好解释的,编译器就是这么干的,需要解释什么?
我把代码简化了一下
程序代码:
#include <stdio.h>
int main()
{
    const int a=1;
    printf("%d\n",a);
    int *p=(int *)&a;
    *p=2;
    printf("%d\n",a);
}

然后用gcc和g++分别编译,运行结果是不同的,gcc上输出是1 2,g++上是1 1,再用-S看
gcc生成的汇编代码
    .file    "temp.c"
    .def    ___main;    .scl    2;    .type    32;    .endef
    .text
LC0:
    .ascii "%d\12\0"
.globl _main
    .def    _main;    .scl    2;    .type    32;    .endef
_main:
    pushl    %ebp
    movl    %esp, %ebp
    subl    $24, %esp
    andl    $-16, %esp
    movl    $0, %eax
    movl    %eax, -12(%ebp)
    movl    -12(%ebp), %eax
    call    __alloca
    call    ___main
    movl    $1, -4(%ebp)
    movl    -4(%ebp), %eax
    movl    %eax, 4(%esp)
    movl    $LC0, (%esp)
    call    _printf
    leal    -4(%ebp), %eax
    movl    %eax, -8(%ebp)
    movl    -8(%ebp), %eax
    movl    $2, (%eax)
    movl    -4(%ebp), %eax
    movl    %eax, 4(%esp)
    movl    $LC0, (%esp)
    call    _printf
    leave
    ret
    .def    _printf;    .scl    2;    .type    32;    .endef

g++生成的汇编代码
    .file    "temp.c"
    .def    ___main;    .scl    2;    .type    32;    .endef
    .text
LC0:
    .ascii "%d\12\0"
    .align 2
.globl _main
    .def    _main;    .scl    2;    .type    32;    .endef
_main:
    pushl    %ebp
    movl    %esp, %ebp
    subl    $24, %esp
    andl    $-16, %esp
    movl    $0, %eax
    movl    %eax, -12(%ebp)
    movl    -12(%ebp), %eax
    call    __alloca
    call    ___main
    movl    $1, -4(%ebp)
    movl    $1, 4(%esp)
    movl    $LC0, (%esp)
    call    _printf
    leal    -4(%ebp), %eax
    movl    %eax, -8(%ebp)
    movl    -8(%ebp), %eax
    movl    $2, (%eax)
    movl    $1, 4(%esp) //这里
    movl    $LC0, (%esp)
    call    _printf
    movl    $0, %eax
    leave
    ret
    .def    _printf;    .scl    2;    .type    32;    .endef

区别很明显,事实就是这样。
2008-01-29 19:27
天使梦魔
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:37
帖 子:564
专家分:2754
注 册:2007-8-29
得分:0 
呵呵.这是C标准委员会的事.说明白好方便理解

LS用C写的么,不过不同版本的GCC处理还是不大一样.
我不太会C语言,基本上G++对我很重要.
2008-01-30 15:09
eagleboycn
Rank: 1
等 级:新手上路
帖 子:191
专家分:0
注 册:2007-9-26
得分:0 
谢谢两位,18#楼的看不懂,汇编我也只记得mov之类了
谢谢 天使梦魔,我就是想找到原始定义,const运行机制
我觉得这个(const变量可通过指针“改变”)“常理”而言应该是不对的,
但为什么存在?是不是有未知存在的理由?
这样方便理解些。。。。。。。。。

[[it] 本帖最后由 eagleboycn 于 2008-1-31 18:04 编辑 [/it]]

兵法的精要在于韬晦自己
2008-01-31 18:03



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-198738-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.818905 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved