变量的存储类包括范围,可见性和生存期,这有助于在程序运行时跟踪特定变量的存在。 C中存在四种类型的存储类:自动,寄存器,静态和外部。
自动和注册存储类–
- 使用自动或寄存器存储类声明的变量的范围是声明变量的函数或块。
- 变量的可见性是在其中声明变量的函数或块。
- 变量的生命周期是函数/ block开始执行直到函数/ block终止之间的时间。
- 自动变量中变量的内存在堆栈上分配。
- 自动变量可以声明为auto int i或int i。这意味着在函数声明的变量的默认存储类为auto。
- 寄存器变量可以声明为register int i。但是,如果寄存器不可用,编译器将为它提供自动存储类。
- 如果auto或register变量未初始化,则包含垃圾值。
静态存储类–
- 使用静态存储类声明的变量的范围是在其中声明变量的函数或块。
- 变量的可见性是在其中声明变量的函数或块。
- 静态变量将保留在内存中,直到程序终止。因此,静态变量仅初始化一次,并且在函数调用期间保持静态变量的值。
- 自动变量的内存分配在堆中,静态变量的内存分配在数据段中。有关详细信息,请参考C程序的内存布局。
- 静态变量可以声明为static int i。
- 如果声明时未初始化静态变量,则使用默认值初始化;例如;如果是整数,则为0。
外部存储类别–
- Extern存储类用于扩展变量的可见性,其中变量是在程序的其他位置(在同一文件或不同文件中)定义的。
- 可以将extern变量声明为extern int i。但是,未将内存分配给i,因为它引用了在程序中其他位置定义的另一个变量i。
本地/全球范围–
在函数或块中声明的变量仅在该函数/ block中具有其作用域。但是,在函数外部声明的变量具有全局范围,可以由任何函数或块访问。
笔记:
- 如果函数具有与全局变量同名的局部/静态变量,则使用局部/静态值。
- 如果某个函数在局部范围内找不到必需的变量,则它将在全局范围内搜索该变量。如果在全局范围内都找不到,则会引发错误。
Que – 1.关于存储类,以下哪个陈述不正确?
(A)具有自动存储类的变量在声明该函数中具有局部作用域。
(B)具有静态存储类的变量在声明它的函数中具有局部作用域。
(C)如果CPU中的寄存器不可用,则具有寄存器存储类的变量声明将返回错误。
(D)无
解决方案:选项A和B是正确的,因为自动以及静态存储类具有本地范围。但是,选项C不正确,因为如果寄存器不可用,则寄存器存储类将转换为自动存储类,它将给出警告,而不是错误。
Que –2。在随后的C程序执行结束时j的值。 (GATE CS 2000)
int incr (int i)
{
static int count = 0;
count = count + i;
return (count);
}
main ()
{
int i, j;
for (i = 0; i <=4; i++)
j = incr(i);
}
(A)10
(B)4
(C)6
(D)7
解决方案: for循环执行为:
对于i = 0,count将在堆中分配内存并初始化为0。语句count = count + i将使count = 0 + 0 = 0。
对于i = 1,使用计数的先前值。语句count = count + i将使count = 0 + 1 = 1。
对于i = 2,使用计数的先前值。语句count = count + i将使count = 1 + 2 = 3。
同样,将3和4分别添加到i = 3和4的计数变量中。因此,答案将是3 + 3 + 4 = 10。
Que – 3.考虑以下C程序
int a, b, c = 0;
void prtFun (void);
int main ()
{
static int a = 1; /* line 1 */
prtFun();
a += 1;
prtFun();
printf ( "\n %d %d ", a, b) ;
}
void prtFun (void)
{
static int a = 2; /* line 2 */
int b = 1;
a += ++b;
printf (" \n %d %d ", a, b);
}
给定的代码段将产生什么输出?
(一种)
3 1
4 1
4 2
(B)
4 2
6 1
6 1
(C)
4 2
6 2
2 0
(D)
3 1
5 2
5 2
解决方案:该程序按以下方式执行:
首先,全局变量a,b和c将被初始化为0。在调用main之后,main中的静态变量a将被初始化为1。
首次调用prtFun()时,静态变量a初始化为2,局部变量b初始化为1。可以将语句a + = ++ b分解为++ b,后跟a = a + b。因此,b将增加到2。另外,a的值将是2 + 2 =4。因此,print语句将输出4,2。从函数返回后,变量b将被销毁(局部作用域),a的值将被保存。
从第一个ptrFun()返回后,将执行语句a + = 1,并且main中的静态变量a将增加为2。
当第二次调用prtFun()时,局部变量b初始化为1。语句a + = ++ b可分解为++ b,后跟a = a + b。因此,b将增加到2。此外,a的值将是= 4 + 2 =6。因此,print语句将打印6、2。
从第二个prtFun()返回后,主函数具有值为2的静态变量a和值为0的全局变量b。因此,输出2、0。
因此,答案是(C)。
Que – 4.考虑下面给出的C函数。
int f(int j)
{
static int i = 50;
int k;
if (i == j)
{
printf("something");
k = f(i);
return 0;
}
else return 0;
}
以下哪一项是TRUE?
(A)该函数对所有j值返回0。
(B)函数为j的所有值打印字符串。
(C)当j = 50时,该函数返回0。
(D)当j = 50时,该函数将耗尽运行时堆栈或运行到无限循环
解决方案:当j为50以外的任何其他值时,如果条件失败,则返回0。
当j为50时,如果条件为true,则函数将被一次又一次地调用。它可能耗尽运行时堆栈或陷入无限循环。
选项(D)是正确的。
Que – 5.考虑下面的C程序。
# include
# define print(x) printf ("%d", x)
int x;
void Q(int z)
{
z += x;
print(z);
}
void P(int *y)
{
int x = *y+2;
Q(x);
*y = x-1;
print(x);
}
main(void)
{
x = 5;
P(&x);
print(x);
getchar();
}
该程序的输出是:(GATE CS 2003)
(A)12 7 6
(B)22 12 11
(C)14 6 6
(D)7 6 6
解决方案:变量x在具有全局范围的main()外部声明。同样,它也在P()中声明。因此,P()将使用x局部于P()。
第一个main()会将全局x更改为5。
通过在y中传递全局x的地址来调用函数P()。因此,y包含全局x的地址。
在P中声明了一个新变量x,并将其初始化为* y + 2 = 5 + 2 =7。因此,P()的局部x的值为7。
通过在z中传递P()的局部x来调用函数Q()。因此,z包含值7。
语句z + = x将全局x的值添加到z。因此,将打印z = z + x = 7 + 5 = 12。
从Q()返回后,将执行语句* y = x-1。由于局部x的值为7,并且y表示全局x,因此全局x的值为7-1 =6。但是,print(x)将打印局部x。因此,将打印7。
从P()返回后,主函数将打印x(x的全局值),该值为6。因此,将打印6。
因此,输出为(A)。