📜  存储类的问题解决和变量作用域

📅  最后修改于: 2021-05-26 02:31:49             🧑  作者: Mango

变量的存储类包括范围,可见性和生存期,这有助于在程序运行时跟踪特定变量的存在。 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)。

想要从精选的最佳视频中学习和练习问题,请查看《基础知识到高级C的C基础课程》。