C Primer Plus Notes 10
1、
从硬件方面来看,被储存的每个值都占用一定的物理内存,C语言把这样的一块内存称为对象(object)。
2、
int entity = 3;
该声明创建了一个名为entity的标识符(identifier)。
3、
int *pt = &entity;
int ranks[10];
第1行声明中,pt是一个标识符,它指定了一个储存地址的对象。但是,表达式*pt不是标识符,因为它不是一个名称。然而,它确实指定了一个对象,在这种情况下,它与entity指定的对象相同。一般而言,那些指定对象的表达式被称为左值。所以,entity既是标识符也是左值;*pt既是表达式也是左值。
4、
作用域:描述程序中可访问标识符的区域。
声明在内层块中的变量,其作用域仅局限于该声明所在的块。
for(int i = 0; i < 10; i++)
printf("A C99 feature: i = %d", i);
上面for循环中的变量i被视为for循环块的一部分,它的作用域仅限于for循环,一旦程序离开for循环,就不能再访问i。
5、
变量的定义在函数的外面,具有文件作用域(file scope)。具有文件作用域的变量,从它的定义处到该定义所在文件的末尾均可见。
#include <stdio.h>
int units = 0;
void critic(void);
int main(void)
{
...
}
void critic(void)
{
...
}
这里,变量 units 具有文件作用域,main( ) 和 critic( ) 函数都可以使用它。由于这样的变量可用于多个函数,所以文件作用域变量也称为全局变量(global variable)。
上面for循环中的变量i被视为for循环块的一部分,它的作用域仅限于for循环。一旦程序离开for循环,就不能再访问i。
6、
C变量有3种链接属性:外部链接、内部链接或无链接。
具有块作用域、函数作用域或函数原型作用域的变量都是无链接变量,这意味着这些变量属于定义它们的块、函数或原型私有。具有文件作用域的变量可以是外部链接或内部链接。外部链接变量可以在多文件程序中使用,内部链接变量只能在一个翻译单元中使用。
默认情况下,文件作用域的变量具有外部链接;使用 static 关键字修饰的文件作用域变量具有内部链接。
7、
C对象有4种存储期:静态存储期、线程存储期、自动存储期、动态分配存储期。
①如果对象具有静态存储期,那么它在程序的执行期间一直存在。文件作用域变量具有静态存储期。
②线程存储期用于并发程序设计,程序执行可被分为多个线程。具有线程存储期的对象,从被声明时到线程结束一直存在。
③块作用域的变量通常都具有自动存储期。当程序进入定义这些变量的块时,为这些变量分配内存;当退出这个块时,释放刚才为变量分配的内存。
块作用域变量也能具有静态存储期。要把变量声明在块中,且在声明前面加上关键字static。
属于自动存储类别的变量具有自动存储期、块作用域且无链接。默认情况下,声明在块或函数头中的任何变量都属于自动存储类别。
8、
静态变量的意思是该变量在内存中原地不动,并不是说它的值不变。
void trystat(void)
{
int fade = 1;
static int stay = 1;
}
第2条声明实际上并不是 trystat( ) 函数的一部分,如果逐步调试该程序会发现,程序似乎跳过了这条声明。这是因为静态变量和外部变量在程序被载入内存时已执行完毕。把这条声明放在 trystat( ) 函数中是为了告诉编译器只有 trystat( ) 函数才能看到该变量。这条声明并未在运行时执行。
9、
int Hocus;
int magic( );
int main(void)
{
int Hocus; // 声明 Hocus ,默认是自动变量
...
}
int Pocus;
int magic( )
{
auto int Hocus; // 把局部变量 Hocus 显式声明为自动变量
...
}
上述例子中,创建了4个独立的变量。main( ) 中的 Hocus 变量默认是自动变量,属于 main( ) 私有。magic( )中的 Hocus 变量被显式声明为自动,只有 magic( ) 可用。外部变量 Hocus 对 main( ) 和 magic( ) 均不可见,但是对该文件中未创建局部 Hocus 变量的其他函数可见。最后, Pocus 是外部变量, magic( )可见,但是 main( ) 不可见,因为 Pocus 被声明在 main( )后面。
10、
int tern = 1;
main( )
{
    extern int tern;
}
第1次声明为变量预留了存储空间,该声明构成了变量的定义。(定义声明:defining declaration)
第2次声明只告诉编译器使用之前已创建的tern变量,所以这不是定义。(引用式声明: referencing declaration)。
外部变量只能初始化一次,且必须在定义该变量时进行。
11、
auto 说明符表明变量是自动存储期,只能用于块作用域的变量声明中。
register 说明符也只用于块作用域的变量,它把变量归为寄存器存储类别,请求最快速访问该变量。同时,还保护了该变量的地址不被获取。
static 说明符创建的对象具有静态存储期,载入程序时创建对象,当程序结束时对象消失。如果 static 用于文件作用域声明,作用域受限于该文件。如果 static 用于块作用域声明,作用域则受限于该块。因此,只要程序在运行对象就存在并保留其值,但是只有在执行块内的代码时,才能通过标识符访问。块作用域的静态变量无链接。文件作用域的静态变量具有内部链接。
extern 说明符表明声明的变量定义在别处。
12、
malloc( )函数:
接受一个参数(所需内存的字节数),找到合适的空闲内存块,这样的内存是匿名的。但是函数返回动态分配内存块的首字节地址。因此,可以把该地址赋给一个指针变量,并使用指针访问这块内存。因为char表示1字节,malloc( )的返回类型通常被定义为指向char的指针。
可以使用 malloc( )函数创建动态数组:
double *ptd;
int n;
scanf("%d", &n);
ptd = (double *)malloc(n * sizeof(double));
free(ptd); // 释放 malloc( ) 分配的内存
13、
free( )所用的指针变量可以与malloc( )的指针变量不同,但是两个指针必须储存相同的地址。也不能释放同一块内存两次。
14、
程序把它可用的内存分为3部分:一部分供具有外部链接、内部链接和无链接的静态变量使用;一部分供自动变量使用;一部分供动态内存分配。
静态存储类别所用的内存数量在编译时确定,只要程序还在运行,就可访问储存在该部分的数据。该类别的变量在程序开始执行时被创建,在程序结束时被销毁。
自动存储类别的变量在程序进入变量定义所在块时存在,在程序离开块时消失。这部分的内存通常作为栈来处理,这意味着新创建的变量按顺序加入内存,然后以相反的顺序销毁。
动态分配的内存在调用malloc( )或相关函数时存在,在调用free( )后释放。所以内存块可以在一个函数中创建,在另一个函数中销毁。未使用的内存块分散在已使用的内存块之间,故使用动态内存通常比使用栈内存慢。
15、
const float *pt; 或 float const *pt;
创建了pt指向的值不能被改变,而pt本身的值可以改变(可以指向其他位置)。
float * const pt;
创建的指针pt本身的值不能更改。pt必须指向同一个地址,但是它所指向的值可以改变。
const float * const pt;
表明pt既不能指向别处,他所指向的值也不能改变。
注:const放在*左侧任意位置,限定了指针指向的数据不能改变;const放在*的右侧,限定了指针本身不能改变。
