总共有auto,static,register,extern
C语言提供了另一种变量,即寄存器变量。这种变量存放在CPU的寄存器中,使用时,不需要访问内存,而直接从寄存器中读写,这样可提高效率。
寄存器变量是个临时变量,当调用完之后,会自动释放,以节约内存空间,提高程序效率。
寄存器变量没有地址,没有地址就不能用指针变量指向它。
寄存器变量的说明符是register,对于循环次数较多的循环控制变量及循环体内反复使用的变量均可定义为寄存器变量。
C语言可以把变量定义为寄存器类型的,将数据直接存放在CPU的寄存器中,使用关键字register定义变量。
例如register a=123;定义a为寄存器类型变量。
对于register变量需要注意的几点:
(1)使用register定义的变量尽可能存放到寄存器中,但不绝对。
(2)定义的变量一般整数(int)为宜。
(3)定义的变量,只要涉及到该变量的地址时,编译器都会报错,如"&a",数组首地址a。
(4)也可以定义指针类型的变量,如register *ptr=&c,c="abcde",c不是register变量。*ptr='a',ptr++移动4个字节。
(5)不能使用sizeof(register)。
一直想测试一下寄存器变量和自动变量的效率问题,很多人都说寄存器变量一般现在都是由编译器自动优化的,没看到网上有关于这个测试程序,所以想自己写程序看下linux下gcc用和不用寄存器变量有什么差别。恰好又看到局部静态变量的问题,三者放到一起做了个简单对比。
我们做个简单的加法:
输入一个长整型数k,计算s=-k+(-k+1)+...+0+1+...+(k-1)+k的值,使用for循环直接加。
当然,为了防止溢出,s为长长整型。(省事,其实要是用s=(-k+k)+(-k+1+k-1)+...+(-1+1)+0来算是可以不用长长整型的)
结果显示:
寄存器变量比用静态局部变量约快一倍,比用自动变量约快两倍。
(我的系统是Ubuntu10.04
amd64,gcc版本4.4.3。)
k=10000000000,也就是10^10时
得到结果:
10000000000
Using r: -10000000000+(-10000000000+1)+...+0+1+...+10000000000=0
Using r take 27.260935 second
Using s: -10000000000+(-10000000000+1)+...+0+1+...+10000000000=0
Using s take 61.445107 second
Using n: -10000000000+(-10000000000+1)+...+0+1+...+10000000000=0
Using n take 81.149198 second
100000
Using r: -100000+(-100000+1)+...+0+1+...+100000=0
Using r take 0.000621 second
Using s: -100000+(-100000+1)+...+0+1+...+100000=0
Using s take 0.001172 second
Using n: -100000+(-100000+1)+...+0+1+...+100000=0
Using n take 0.001877 secoond
另:
我最开始用递归的方法来做这个事,然后发现寄存器变量用的时间反而是最长的,估计可能是每次分配时都要给寄存器变量分配空间,实际上分配到的很快就是内存了。
用g++编译的,寄存器变量效率比用gcc要略低点(20%左右),但是使用其它两种变量都要比用gcc高点(30%)。
似乎gcc对自动变量优化做得很少?还是需要手工设置编译参数优化?
源程序:
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
long long add_reg(long);
long long add_sta(long);
long long add_nor(long);
long cal_time(long,char);
int main()
{
long long s;
long n;
char method;
scanf("%ld",&n);
method='r';
s=cal_time(n,method);
method='s';
s=cal_time(n,method);
method='n';
s=cal_time(n,method);
}
long cal_time(long n,char method)
{
struct timeval start,end;
double tc;
long long s;
//记录开始时间(recording start time)
gettimeofday( &start, NULL );
switch(method)
{
case 'r':
s=add_reg(n); //使用寄存器
break;
case 's':
s=add_sta(n); //使用局部静态变量
break;
case 'n':
s=add_nor(n); //使用一般的自动变量
break;
default:
printf("Wrong method.");
}
//记录结束时间(recording end time)
gettimeofday( &end, NULL );
//显示计算的时间(display caculation time using cpu)
tc = 1000000 * ( end.tv_sec - start.tv_sec
) + end.tv_usec
- start.tv_usec;
tc /= 1000000;
printf("Using %c: -%ld+(-%ld+1)+...+0+1+...+%ld=%lld\n",method,n,n,n,s);
printf("Using %c take %f second\n\n",method,tc);
return s;
}
long long add_reg(long k)
{
register long i=0;
register long long s=0;
for(i=-k;i<=k;i++)s=s+i;
return s;
}
long long add_sta(long k)
{
static long i;
static long long s=0;
for(i=-k;i<=k;i++)s=s+i;
return s;
}
long long add_nor(long k)
{
long i;
long long s=0;
for(i=-k;i<=k;i++)s=s+i;
return s;
}