c与指针(三)

来源:互联网 发布:周易算法49 编辑:程序博客网 时间:2024/05/01 09:44
基本声明
格式:说明符(一个或者多个) 声明表达式列表(这个就是语法)
说明符(specifier)就是特殊的关键字.....很多说明符是表达同一个意思。这个可以百度。搜索 相等的声明
例如 short a;等同于 short int a;
初始化
在一个生命中可以各一个标量变量指定一个初始值。例如int i=5;
声明简单数组。
eg:int value[10];
声明指针 (看看指针多蛋疼)
eg: int *a;常见的指针声明。 int* a;这个也是指针。
然后int* a,b,c; 这个是a是指针,b,c就是整型了。
这是因为,*这个符号是间接寻址,或者说间接访问。 int是指后面跟的变量的类型。*是一个运算符,他表示后面变量的地址。于是 *a 我们就可以推断a是一个指针。而在int* a,b,c;中仅仅有a前面有*运算符,b和c没有。
再看一个例子
char *message="goodbye world";这个是将字符串常量的第一个地址初始化给这个指针。

这个和 char *message;message="goodbye world";一样。

隐式声明
c语言中有几种声明,他的类型名可以忽略。就是说c语言里有几种东西编译器会默认为整形。建议别用。你不写,是真的不想写还是忘了写,这个问题很蛋疼。是什么就是什么写清楚。
typedef
c语言支持一种叫做tyepdef的机制,它允许你为各种数据类型定义新名字。typedef声明的写法和普通的声明基本相同,只是把typedef这个关键字出现在声明的前面。例如,下面这个声明:char *ptr_to_char;在这个之前加上tyepdef声明变为typedef char *ptr_to_char;。
这个声明吧表示符ptr_to_char作为指向字符的指针类型的新名字。你可以像使用任何预定义名字一在下面的声明中使用这个东西。eg: ptr_to_char a;

常量
ANSIC允许声明常量。常量的样子和变量完全一样。只是常量的值不能修改。用const定义。
eg : const int a;和int const a;一样。对于常量的初始化应该在定义的时候搞。
当涉及到指针变量的时候有两种东西可以作为常量。
指针变量和他所指向的实体。eg int *pi;pi是一个普通的指向整型的指针。而变量int const *pci就是一个指向整型常量的指针。可以写该指针的值,但不能修改它所指向的值。相比之下,int *const cpi则是声明衣蛾指向整型的常量指针。此时指针是常量,他的至无法修改。但是他所指向的值可以修改。int const *const cpci;这个什么都不能改。
#define是另一种创建名字常量的机制。但是#define要比const好。因为const只能在可以使用变量的地方使用。

作用域
当变量在程序某个部分被声明的时候,他只有在程序的一定区域才能被访问到。这个区域是有标示符作用域(scope)决定的。
编译器确定了4中作用域,文件作用域,函数作用域,代码块作用域,原型作用域。
表示符声明的位置,决定了他的作用域。位于一对大括号之间的所有语句称之为一个代码块。任何在代码块的开始声明的标示符都具有代码块作用域。
文件作用域是值在所有代码块之外声明的标示符。
原型作用域只适合于在函数原型中声明的参数名。
函数作用域只适用于语句标签。语句标签用于goto语句。一个函数中的所有语句标签必须唯一。这个基本上不要用。(代码逻辑容易乱)

存储类型
存储类型是值存储变量的内存类型。变量的存储类型决定变量何时创建,何时销毁,以及它的值将要保留多久。有三个地方可以用于存储变量:普通内存,运行时堆栈,硬件寄存器。(不懂的去补补计算机原理,不是计算机专业的不用管)

变量的缺省存储类型,取决与他的声明位置。凡是在任何代码之外声明的变量重视存储与静态内存中,也就是不属于堆栈的内存,这类变量称之为静态变量。对于这类变量,无法指定其他的存储类型。静态变量创建于程序运行之前。在整个程序运行过程中,始终存在。他的值一般不会变,除非进行赋值,或者是程序结束。

在代码块内部声明的变量的缺省存储类型是自动的,也就是它存储在堆栈中,称之为自动变量。有意个关键字auto就是用于修饰这种存储类型。基本不用,因为在代码块内部的时候,不写就是自动变量。程序执行到自动变量的位置时才会创建这个变量。离开这个代码快的时候,会自动销毁这个东西。假如反复调用一个函数,这个东西就会不断的创建销毁。

对于代码块内部声明的变量如果加上static,可以是它称为静态变量。静态变量会一直存在与内存。记住,函数形参不能用于递归。

最后,关键字register可以用于自动变量的声明,提示他们应该存储与机器的硬件寄存器而不是内存中。这种变量称之为寄存器变量。这个基本也不用,因为计算机寄存器存的东西不多,基本上他会自动判断那几个是register。如果这个东西它多,他就只保留前几个。而且编译器一般会自动认定那一个比较适合是register。它的创建和销毁时间和自动变量相同。但是它需要在函数返回值前恢复到之前存储的值。确保寄存器变量没有被损坏。由于这个东西的保存和恢复,所以计算机不会提供寄存器变量的地址。

综上所述,这个就是讲了一下三种存储变量的地方。

速度排名是寄存器,堆栈,内存。由于静态变量以及堆栈对于变量创建和销毁的时间没有智能的判断,仅仅是依靠代码来做,这样会使得c语言程序特别大的时候静态变量特别消耗内存,而且运算很慢.....这个算是c语言的缺点。但是这个也是c语言的优点,因为程序员可以决定这些变量到底是什么类型从而不断的优化代码,调试程序。

爱是他,恨是他,么么哒~~~

初始化
自动变量和静态变量的初始化时有一个重要的差别。在静态变量的初始化中,我们可以把可执行程序文件想要初始化的值放在当前程序执行时变量将会使用的位置。当可执行文件载入到内存时,这个已经保存了正确初始值的位置将赋值给那个变量。完成这个过程不需要额外得到指令,变量也将会得到正确的值。如果,不显式的指定其初始变量值,静态变量将初始化为0。
自动变量的初始化需要更多的开销,因为当成需链接时还无法判断自动变量的存储位置。事实上,函数的局部变量在函数的每次调用中科能占据不同的位置。基于这个理由,自动变量没有缺省的初始值,而显式的初始化将在初始化处插入一条隐式的赋值语句。
这个技巧造成的后果有:
1.自动变量的初始化较之赋值语句效率并无提高。除了声明为const的变量之外,在声明变量的同时进行初始化和先声明后赋值只有风格之差,并无效率之别。
2.这条隐式的赋值语句使自动变量在程序执行到他们所声明的函数或者说是代码快的时候,每次都将重新初始化。这个行为与静态变量大不相同。后者只是在程序开始执行前初始化一次。
3.由于初始化在运行是执行,你可以用任何表达式作为初始化的值。例如:
int func(inta){int b=a+3;}
4.除非你对自动变量进行显式的初始化,否则当自动变量创建是,他的值总是垃圾。Static关键字
当用于不同的上下文环境是,static关键字具有不同的意思。当他用于函数定义时,或用与代码快之外的变量声明是,static关键字用于修改标识符的链接属性,从external改为internal,但是标识符存储类型和作用域不受影响。用着中方是声明的函数或者变量只能在声明他们的源文件中访问。
当它用于代码块内部的变量声明时,static关键字用于改变变量的存储类型,从自动变量修改为静态变量,但变量的链接属性和作用域不受影响。用这种方式声明的变来年个在程序执行之前创建,并在程序的整个执行期间一直存在,而不是名词在代码块开始执行的时候创建,在代码块执行之后销毁。


当它用于代码块内部的变量声明时,static关键字用于改变变量的存储类型,从自动变量修改为静态变量,但变量的链接属性和作用域不受影响。用这种方式声明的变来年个在程序执行之前创建,并在程序的整个执行期间一直存在,而不是名词在代码块开始执行的时候创建,在代码块执行之后销毁。

变量abc,存储类型为静态。他们在程序之前创建,知道程序结束。当程序开始执行的时候,变量a初始化为5.这些变量的作用域一直延伸到这个源文件结束为止。第6行和第12行的ab在那部分程序中将隐藏同名的静态变量。因此这个变量的作用域为a112,17~29.b262529  c:3~29

       第4行声明了2个标识符。d的作用域从第4行直到文件结束。函数d的定义对于这个源文件中任何以后想要调用它的函数起到了函数原型的作用。作为函数名,d在缺省情况下具有external链接属性,所以其他源文件只要在文件上存在d的原型,就可以调用d。如果声明为static就可以把它的链接属性从external改为internal。但这样将使其他源文件不能访问这个函数。对于函数而言,存储类型不是问题。因为代码总是存储在静态内存中。

       参数e不具有连接属性,所以为们只能从函数内部通过名字访问它。它具有自动存储类型,所以它在函数调用时创建,当函数返回时消失。由于局部变量冲突,它的作用域于第511行。第1618行,以及2223行。

        第57行声明局部变量。所以他们的作用域到函数结束为止。他们不具有链接属性,所以他们不能在函数被调用时,它通过隐式赋值被初始化15.b的类型是寄存器类型。他的初始值是垃圾。g是静态,他会在程序的整个执行过程中一直存在。当程序开始执行的时候,它被初始化为20.当函数每次被调用的时候,它并不会被重新初始化。

        第8行声明基本不用。

         第11行和12行为代码声明局部变量。他们都具有自动存储类型,不具有链接属性,他们的作用域延伸到第16行。这些变量和先前声明声明的ac不同。而且由于名字冲突,以前声明的变量是不能北访问的。

       第13行使全局变量h在这个代码块内可以被访问。它具有external链接属性,存储于静态内存中,这个唯一一个必须是用使用extern的声明。如果没有h就是一个局部变量。

       第18行和19行用于创建局部变量(自动无连接作用域与本代码快)。这个e和参数e是不同变量。他和第11行的e也不同。这个代码块中从10行到17行并没有嵌套,所以编译器可以使用相同内存来存储这两个代码块中不同的变量e。如果你想要让这两个代码快中的e表示同一个变量,那么这个e就不应该是局部变量。

       最后,24行声明了函数i,它具有静态链接属性,静态链接属性可以放置它背着个源文件之外的任何函数调用。函数d不可以调用i,因为d不存在i的原型。




原创粉丝点击