在C语言中我们可以给变量指定属性,因此在我们的C语言关键字中有一种关键字叫属性关键字,是用来指定变量特有的属性。
一、AUTO即就是C语言中局部变量的默认属性
编译器默认所有的局部变量都是AUTO的。AUTO还有另外的一种含义,就是在内存的栈上面分配空间。堆栈是一个动态分配内存空间的地方。
二、static 关键字指明变量的静态属性。
1.static 关键字同时具有作用于限定符的意义,即文件作用域标识符。文件作用域的意思就是定义的这个变量就限于当前文件时全局的其他文件是不可以访问的。
-static 修饰的全局变量作用域只限于声明的文件中
-static 修饰的函数作用域只限于声明的文件中
2.static 修饰的局部变量存储在程序静态区
例如:
1.其他文件可以访问的情况:
test1.c
int myInt = 0; //在test1.c中定义一个全局变量没有使用static修饰的情况下。test2.c可以调用
int MyFunction() //在test1.c中定义一个全局函数没有使用static修饰的情况下。test2.c可以调用
{
return myInt;
}
test2.c
#include<stdio.h>
extern myInt; //extern关键字是引用其他文件中定义的变量或函数。
extern MyFunction();
int main(viod)
{
int j = 0;
for (j = 0 ;j<5;j++)
{
printf("%d\n",MyFunction());
printf("%d\n",myInt);
}
return 0;
}
2.其他文件不能访问的情况:
test1.c
static myInt = 0; //由于使用了static修饰因此其他文件时不可以访问的
static int MyFunction() //由于使用了static修饰因此其他文件时不可以访问的
{
return 0;
}
test2.c
#include<stdio.h>
extern myInt; //extern关键字是引用其他文件中定义的变量或函数。
extern MyFunction();
int main(viod)
{
int j = 0;
for (j = 0 ;j<5;j++)
{
printf("%d\n",MyFunction());
printf("%d\n",myInt);
}
return 0;
}
这种情况进行编译时会报错。
三、register
1.register 关键字指明将变量存储于寄存器中也就是说cpu中,register 只是请求存储器变量,但不一定请求成功。必须达到一定的条件才能成功,如要达到寄存器可以接受的字节长度。在一般的情况下,cpu寄存器只是尽量的把这个变量当做cpu寄存器的变量进行存储,但不一定成功的。
2.不能使用取地址符(&)来获取register变量的地址。因为存放在cpu寄存器中,使用取地址符是取不到的,&是取内存中的地址。
3.我们知道栈中的变量是经常变换的,因此如果我们定义一个全局变量使用auto进行修饰时会报错(例1-1)。如果使用register进行修饰的时候同样
会出现错误的(例1-1),因此如果我们允许变量长期的存放到寄存器中,如果寄寄存器没有可以使用的空间的时候就会造成cpu无法工作。因此在C语言中是不可
以存放全局变量到寄存器中。
例如1-1:
#include<stdio.h>
static int l;
register int s;
auto int m;
int main(viod)
{
static int i;
register int j;
return 0;
}
4.register修饰的变量发在cpu寄存器中,在cpu寄存器中变量取得速度远高于内存中的变量,因此在实时性的系统中或者要求性能很高
的系统中往往会把变量存放在cpu寄存器中。
对比使用了register 和不使用register的区别:
--使用register
---------------------------------------------------------------
#include<stdio.h>
#include<sys/time.h>
int main(int arg ,char * argv[])
{
struct timeval start,end;
gettimeofday(&start,NULL);//start time
double timeuse;
register double sum;
register int j,k;
for(j=0;j<1000000000;j++){
for(k=0;k<10;k++)
{
sum = sum+1.0;
}
}
gettimeofday(&end,NULL);
timeuse = 1000000 * (end.tv_sec - start.tv_sec)+end.tv_usec-start.tv_usec;
timeuse/=1000000;
printf("running time :%f\n",timeuse);
return 0;
}
消耗的时间为:running time :8.547920
---------------------------------------------------------------
--不是用register
--------------------------------------------------------------
#include<stdio.h>
#include<sys/time.h>
int main(int arg ,char * argv[])
{
struct timeval start,end;
gettimeofday(&start,NULL);//start time
double timeuse;
double sum;
int j,k;
for(j=0;j<1000000000;j++){
for(k=0;k<10;k++)
{
sum = sum+1.0;
}
}
gettimeofday(&end,NULL); //end time
timeuse = 1000000 * (end.tv_sec - start.tv_sec)+end.tv_usec-start.tv_usec;
timeuse/=1000000;
printf("running time :%f\n",timeuse);
return 0;
}
消耗的时间为:running time:34.287267
---------------------------------------------------------------
在这里我们使用到了struct timeval 结构体和gettimeofday()函数。
结构体的定义为:
---------------------------------------------------------------
struct timeval
{
__time_t tv_sec; /* Seconds. */
__suseconds_t tv_usec; /* Microseconds. */
};
---------------------------------------------------------------
函数:
---------------------------------------------------------------
/* Get the current time of day and timezone information,
putting it into *TV and *TZ. If TZ is NULL, *TZ is not filled.
Returns 0 on success, -1 on errors.
NOTE: This form of timezone information is obsolete.
Use the functions and variables declared in <time.h> instead. */
extern int gettimeofday (struct timeval *__restrict __tv,
__timezone_ptr_t __tz) __THROW __nonnull ((1));
---------------------------------------------------------------
gettimeofday()功能是得到当前时间和时区,分别写到tv和tz中,如果tz为NULL则不向tz写入。