C/C++中取地址符&的语义和static变量

C中变量的存储方式

1.函数中的局部变量如不作专门说明,都之auto的,即动态存储的,auto可以省略。局部变量也可以定义为static的,这时它在函数内值是不变的

2.静态局部变量如不赋初值,编译时系统自动赋值为0,动态局部变量如不赋初值,则它的值是个不确定的值

3。C规定,只有在定义全局变量和局部静态变量时才能对数组赋初值。 //不太懂

4.为提高执行效率,c允许将局部变量值放在寄存器中,这种变量叫register变量,要用register说明。但只有局部动态变量和形式参数可以作为register变量,其它不行。
52) 全局变量的存储方式
全局变量在函数外部定义,编译时分配在静态存储区,可以在程序中各个函数所引用。多个文件的情况如何引用全局变量呢?假如在一个文件定义全局变量,在别的文件引用,就要在此文件中用extern对全局变量说明,但如果全局变量定义时用static的话,此全局变量就只能在本文件中引用了,而不能被其它文件引用。

/*
* test_memory.c
*
* Created on: 2009-10-3
* Author: lengyuex
*/

#include
#include
#include
static int d=9;
int z = 9;
int *p=&z;
int a;
static int b =10;
static int c;
void swap(int* x,int* y)
{
static int d=8;
int temp;
temp=*x;
*x=*y;
*y=temp;
printf ("in swap() the d=%d\n",d);
}

int main()
{
printf ("no define in main ,the d=%d\n",d);
static int d;
int e;
int f[]={1,2,3,4,5};
int i;
for (i=0;i printf ("the f[i]=%d\n",f[i]);
int t[5];
for (i=0;i t[i]=i+2;
for (i=0;i printf ("the t[i]=%d\n",t[i]);
int x=4,y=5;
printf ("before swap() a=%d,b=%d,c=%d,z=%d,d=%d\n",a,b,c,z,d);
printf ("the no init e=%d\n",e);
swap(&x,&y);
printf ("after swap() d=%d\n",d);
printf("x=%d,y=%d,z=%d,w=%d\n",x,y,z,b);
return 0;
}


输出:
[lengyuex@Tux algorithm]$ ./a.out
no define in main ,the d=9
the f[i]=1
the f[i]=2
the f[i]=3
the f[i]=4
the f[i]=5
the t[i]=2
the t[i]=3
the t[i]=4
the t[i]=5
the t[i]=6
before swap() a=0,b=10,c=0,z=9,d=0
the no init e=11472064
in swap() the d=8
after swap() d=0
x=5,y=4,z=9,w=10


变量存储在什么地方:http://blog.csdn.net/normalnotebook/archive/2006/06/08/781397.aspx



分配效率:栈是机器系统提供的数据结构,电脑会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C 函数库提供的,他的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法能够参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,假如没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程式数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。



C/C++中的指针其实就是一个变量,和其他类型的变量是一个样子的,它是一个占用四字节的变量(32位机上),它与其他变量的不同之处就在于它的变量值是一个内存地址,指向内存的另外一个地方。reference我的理解就是一个别名,它和linux操作系统上的alias是一个样子的。再者,一个 pointer变量可以指向NULL,表示它不指向任何变量地址,但是reference必须在声明的时候就得和一个已经存在的变量相绑定,而且这种绑定不可改变。



在C语言中,&符号大家一定很熟悉吧。

它除了可以作为按位运算“与”之外还有更常用的功能——取变量地址。

我们首先看下面一个简单的例子:


#include
int main(void)
{
int a = 0;
int *p = &a;
printf("The value is: %d\n", *p);
return 0;
}

上面代码中,指针p指向变量a的地址。在C/C++中,每个变量都有其相应的地址,通过在变量标识符前加&符号即可获得变量的地址。

那么我们这么写可以吗?int *p = &0x01000;

这显然不行。因为对于一个数值常量,它是没有地址的。而变量之所以有地址就是因为要有一个存储单元对变量进行标识(当然,变量也可以直接映射到某个寄存器)。

我们再看下面的代码:


#include "stdio.h"
int main(void)
{
int a = 0; // &a = 0x0012ff60
int *p = &*(int*)0x0012ff60;
printf("The value is: %d\n", *p);
return 0;
}

上面代码又是怎么回事呢?

先前已经调查过变量a的地址——0x0012ff60,那么这里的指针p实际上也是指向变量a的地址。

首先,将0x0012ff60作为int*,这时它与&a是等价的。

然后*(int*)0x0012ff60表示取变量a的内容。

最后,&*(int*)0x0012ff60表示再脱去*(int*)0x0012ff60的解引用,相当于又变为(int*)&a。

因此,这里的&与第一个例子中的&是不同的语义。这里的&不是取地址,因为一个*(int*)0x0012ff60不是变量,它是没有地址的。每一个变量标识符在编译期间,编译器会为它们创建一个符号表,其中存放着变量标识符相应的各种属性,如类型、地址标识等。地址标识在连接后即可确定逻辑地址值。简而言之,&作为取地址操作,当且仅当&后面跟着的是变量或函数标识符。所以这里的&表示脱去解引用。

由此我们可以得出:&作为取地址操作时,其行为结果是在编译时就被确定的;而*,解引用操作(或取内容)操作,其行为结果只能在运行时才可被确定。

再看下面的例子,加深印象:


#include "stdio.h"
int main(void)
{
int a = 0;
int *p = &*&*&a;
printf("The value is: %d\n", *p);
return 0;
}


在C++中,&还可以表示引用,这个就不多说了。
#include "iostream"
using namespace std;
int main(void)
{
int a = 0;
int &r = a;
cout return 0;
}


原文 地址:http://blog.csdn.net/wanghua305/archive/2009/07/17/4357103.aspx
posted @ 2009-10-03 19:27  冷月X  阅读(2857)  评论(0编辑  收藏  举报