设为首页 加入收藏

TOP

C语言中 const 和 static 和 extern (二)
2014-11-23 21:58:15 来源: 作者: 【 】 浏览:13
Tags:言中 const static extern

#pragma pack()//sizeof(B)==17

说明:例二中演示了数据对其的情况,由于CPU访问数据的特点是一次访问多个字节,故如果多字节数据的首地址是2的整数倍的话,将可以一次内存访问即可取得其所对应的所有数据,所以一个优化要求就是变量的地址是其数据类型长度的整数倍,例如int a的a的地址要求是4的整数倍。

针对结构体,如果结构体中所有元素类型相同,作为数组处理,入struct A;否则一般都是其最常元素的整数倍,例如struct B和C。这样处理的目的是考虑定义结构体数组的情况,例如struct B b[10];那么这10个结构体变量如果每个长度都是8,将能保证每个变量的第一个元素都能是4的整数倍,否则将达不到这个效果,不能实现高效的内存访问,故编译器将对不符合要求的结构体自动调整数据对齐。

最后需要交代的是,class中的static变量不被分配到栈上,所以不能计入sizeof中,空类的长度是1,有虚函数的长度为4,因为包含一个指向函数表的指针。

下面分析几个面试题:

例一:

int fp1(char var[])//返回值为4,因为var作为参数传递时,已经退化为普通指针,

{//故其大小就是指针的大小,不作为数组名处理,无法计算出数组长度。

returnsizeof(var);

}

例二:

//str1是一个数组名,该数组是一个指针数组,长度为3,故sizeof(str1)为3*4

void fp1(void)

{

char *str1[] ={"hello","mico","china"};

for(int i=0;i

{

printf("%s",str1[i]);

}

}

六、volatile的用法:该词的意思是”易变的”,用于修饰变量的一个关键字,表示该变量在很多地方都能被改变,会被意象不到的改变,编译器不能对其优化,往往用于多任务系统或嵌入式系统中,情况一:嵌入式系统中的很多外设寄存器的值会实时改变,如:#define PTA *(volatile unsigned char *)(0x00000001);情况二:嵌入式系统内存中的某些变量有可能被中断程序修改;情况三:多任务系统中的共享变量可能随时改变。满足这些特点之一的变量必须要用volatile修饰,保证编译器不能对其优化处理,如果被优化,往往程序的执行结果出错。

例一:

int a = 10;

if(a == 10)

{

a = 11;

}

这短代码正常被优化为

a = 11; 但是,如果volatile int a;则这段代码将不被优化。

例二:

//原始代码:

int square(volatile int *ptr)

{

return *ptr * *ptr;

}

//编译器优化完的代码:

int square(volatile int *ptr)

{

int a = *ptr;

int b = *ptr;

return a*b;

}

//正确代码:由于*ptr的值随时可能改变,故优化代码中的a和b的值可能不一样,故计

int square(volatile int *ptr) //算的结果可能有误

{

int a = *ptr;

return a*a;

static有两种用途:一是修饰变量,二是修饰函数

第一:修饰变量

例子:

static int a;

void Func()

{

static int b;

}

全局变量默认的存储类型是extern,若不加static修饰,在不同头文件中定义名字相同的全局变量会发生冲突。static修饰符是一个能够减少这类命名冲突的有用工具。例如,以下声明语句

static int a;

其含义与下面的语句相同:

int a;

只不过,a的作用域限制在一个源文件内,对于其他源文件,a是不可见的。因此,如果若干个函数需要共享一组外部对象,可以将这些函数放到一个源文件中,把它们需要用到的对象也都在同一个源文件中以static修饰符声明。

变量b是个局部变量,在程序退出函数Func后,b就不能被使用。但是当程序再次进入函数Func时,变量b保持上次运行后的值。

第二:修饰函数

static修饰符不仅适用于变量,也适用于函数。一个函数,其默认存储状态也是extern。如果函数f需要调用另一个函数g,而且只有函数f需要调用函数g,我们可以把函数f与函数g都放到同一个源文件中,并且声明函数g为static:

static int

g(int x)

{

// g函数体

}

void f()

{

// 其他内容

b=g (a);

}

我们可以在多个源文件中定义同名的函数g,只要所有的函数g都被定义为static,或者仅仅只有其中一个函数g不是static。因此,为了避免可能出现的命名冲突,如果一个函数仅仅被同一个源文件中的其他函数调用,我们就应该声明该函数为static。

如果说得规范一点,C/C++没有全局变量,只有外部和自动。C/C++里的全局变量是靠你自己做出来的。

所有在某函数里定义的变量全是自动变量。默认是auto。在所有函数外定义的是外部变量。

如果你的程序放在单个源文件里,那它就是全局变量。如果有多个源文件,你在其中一个文件里定义那个变量,再在所有其它文件里用extern说明它。它也成了全局变量。

注意:这里很仔细地使用了“定义”和“说明”。前者引起存储分配,是真正产生那个变量。后者只是让变量在那个文件里也可见(可以访问)。

如果在定义外部变量时,加上指示符static,则生成的是静态外部变量。这种变量的作用域仅限于那个文件。也就是说,不能再在其它文件里用extern说明它。

如果在定义自动变量时,加上指示符static,则生成的是静态自动变量。作用域没变,仍然是所在的语句块。但是生命期却变成永久。

首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇变量,指针,指针变量 下一篇排序算法c语言描述---归并排序

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: