您的位置:首页 > 编程语言 > C语言/C++

c语言学习笔记(1)基本数据类型及auto,register,static分析

2015-09-20 18:29 435 查看
摘要: 解释了c语言中什么是数据类型,什么是变量,他们的真正含义是什么。分析了属性关键字auto,register和static的用法。

一、什么是数据类型

刚看视频的时候,我也理解为就是char,int这些东西,其实这些东西也是指定了我们后面变量他所占的内存的大小,所以数据类型其实是固定内存大小的别名。数据类型又是创建变量的模子。

比如我们char a;a是我们用模子创建出来的,名字叫做a,它的大小是1个字节。任何我们用char创建出来的变量,大小都是一个字节,虽然名称不同,但是他们所占的内存大小是一样的,因为我们的模子大小不会变嘛。

二、什么是变量

比如我们int a;然后就可以对a进行操作,a=10;那么这个10是给到什么地方去了,给了a,a又代表什么?a就代表一段内存。。。所以说,变量其实是一段连续存储空间的别名。程序中通过变量来申请和命名内存空间,通过变量的名字我们就可以使用存储空间。

在c语言中,变量可以有自己的属性,要给变量加上特定的属性,就要在变量前加上属性关键字,属性主要有三种:auto,register和static。

三、auto

auto是c语言局部变量的默认属性,可以加也可以不加,编译器默认所有的局部变量都是auto的。

四、static

static指明变量的“静态”属性,同时具有作用于限定的作用。static修饰的变量存储在程序的静态区,另一个作用是文件作用于标识符。static修饰的全局变量只能作用在声明的文件中,同样,static修饰的函数也只能作用在声明的文件中。

五、register

register声明将变量存储在寄存器里面,register只是请求寄存器变量,但是不一定能够成功,register变量必须是寄存器能够接受的值,不能使用&运算符获取register变量的地址。

为什么要放在寄存器里面呢,我们知道寄存器是比内存快得多的,在一些高要求的实时系统里面,一个多次被调用的函数,放在寄存器里面,会快得多得多。

六、实验测试

1.auto可以修饰的变量范围

我们编写一个测试函数test1.c如下:

#include<stdio.h>

autoint a;
 
intmain(void)
{
autoint b=0;
 
return0;
}


完了之后编译,编译指令比较简单,直接gcctest1.c,会生成可执行文件a,但是这里报错信息如下:



这是因为,auto这个关键字只能修饰局部变量,不能修饰全局变量,因为全局变量不是在栈上分配空间的,是在全局静态数据区分配空间的。

2.register可以修饰变量的范围

我们编写一个测试函数test2.c如下:

#include<stdio.h>
 
registerint a;
 
intmain(void)
{
registerint b=0;
 
return0;
}





然后再编译,会报错,说m的寄存器名无效,说明这里全局变量也不能随便用register修饰,这是为什么呢?因为在c语言中,全局变量也不能修饰为register,register是要在寄存器里面申请内存,而全局变量在程序整个运行过程总是一直存在的,也就是说如果这样申明了,那么我们的寄存器中就会一直被一个全局变量占用,这对于cpu来说是不可能的,必然会导致系统出错。

3.不能对register取地址

编写测试函数test3,c如下,目的是打印我们申请到的变量地址,

#include<stdio.h>
 
int main(void)
{
    autoint i =0;
    registerint j =0;
 
    printf("%0x\n",&i);
    printf("%0x\n",&j);
 
return 0;
}





编译时出现以上消息,说要求寄存器变量j的地址。看来是不能吃成功。原因很简单,因为,我们的变量代表的是在内存中的地址,而不是寄存器的地址,寄存器和内存是有本质区别的,所以当然请求不到,输出错误。我们把这个注释掉,看看输出的地址,就是i代表的内存地址。

4.resister修饰局部变量

接着,编写测试函数test4.c,如下:

#include<stdio.h>
 
void f1(void)
{
static int i = 0;
i++;
printf("%d\n",i);
}
 
void f2(void)
{
int i = 0;
i++;
printf("%d\n",i);
}
 
int main(void)
 
{
int j=0;
for(j=0;j<=4;j++)
{
f1();
}
for(j=0;j<=4;j++)
{
f2();
}
return 0;
}


编译gcc test4.c –o test4,生成test文件中之后执行,输出如下结果:




这里两个函数f1和f2之间的区别仅仅在于变量i一个用static修饰了,一个没有,这里为什么一个打印出来的都是1而另外一个是12345呢?这是因为当static修饰一个局部变量的时候,这个局部变量在我们的静态数据区分配空间,也就是说这个变量是不在栈上的,调用该函数之后,这个变量是不会因为函数结束之后被释放。而且,对于静态的局部变量,它只会在第一次被初始化的时候初始化一次!!!这个很重要,所以这里打印出来的数字不同。

5.register限定变量和函数的作用域

编写两个测试文件,一个叫test5-1.c,一个叫test5-2.c,两个文件的内容分别如下:

<span style="font-size:18px;">test5-1.c
#include <stdio.h>
 
extern int test5_g;
extern int test5_fun();
 
int main(void)
{
printf("%d\n",test5_g);
printf("%d\n",test5_fun());
 
return 0;
}
 
test5-2.c
#include <stdio.h>
 
int test5_g=2015;
 
int test5_fun(void)
{
    returntest5_g;
}</span>


这个两个函数很简单,1调用外部变量和函数,在1里面用extern声明,编译使用以下指令;

#gcc test5-1.c test5-2.c –o test5

生成的可执行文件运行后效果如下:



可以看到引用成功,1把2里面定义的变量和函数引用了,打印出了我们想得到的值。

再下面,修改test5-2.c的定义方法,在变量和函数前面加上static。修改后如下:

#include<stdio.h>
 
staticint test5_g=2015;
 
staticint test5_fun(void)
{
    return test5_g;
}


这时候在编译,出现以下错误:




这时候引用就不成功了,为什么呢?因为static限定了变量和函数的作用域,只在当前文件。我们看到很多驱动函数都加了static,那是因为内核里面的函数太多了,我们自己加的驱动很有可能和别人重名,所以限定其作用范围。

这篇帖子就总结到这里吧,如有不正确的地方,还请指出,大家共同进步!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: