2016.11.15 C语言常遇概念问题



作者:郭孝星
微博:郭孝星的新浪微博
邮箱:allenwells@163.com
博客:http://blog.csdn.net/allenwells
Github:https://github.com/AllenWells

一 基本概念

1.1 关键字static的作用

  1. 在函数体,一个被声明为静态的变量在这一函数被调用的过程中维持其值不变。
  2. 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用的函数调用,但不能被模块外的其他函数访问,它是一个本地的全局变量。
  3. 在模块内,一个被声明为静态的函数只可以被这一模块内的其它函数调用,那就是这个函数被限制在它的模块的本地范围内使用。

1.2 引用和指针的区别

  • 引用变量必须初始化,指针不必。
  • 引用初始化以后不能被改变,指针可以改变所指的对象。
  • 不存在指向空值的引用,但是存在指向空值的指针。

1.3 #include

1.4 全局变量和局部变量在内存中存放位置的区别

全局变量存放在静态区中,局部变量存放在堆栈中。

1.5 堆栈溢出的原因

  • 没有回收垃圾资源。
  • 层次太深的递归调用。

1.6 引用一个已经定义过的全局变量

  • 引用头文件的方式,假如定义的那个变量出错,那么编译器就会报错。
  • 用extern关键字方式引用,假如定义的变量出错,则编译器间不会报错,而在连接期间报错。

1.7 全局变量是否能定义在多个.c文件包含的头文件中

可以,在不同的.c文件中以static形式来声明同名全局变量。前提是其中只能有一个C文件对此变量赋初值,此时连接时不会出错。

1.8 for( ; 1 ; )是什么意思

和while(1)相同,无限循环。

1.9 static 全局变量、局部变量、函数与普通全局变量、局部变量、函数

全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式,两者在存储方式上并无区别。而非静态全局变量在各个源文件中都是有效的,而静态全局变量则只在定义该变量的源文件有效。static全局变量值初始化一次,防止在其它文件单元中被引用。

因此,把局部变量改成静态变量后改变了它的存储方式即该变了它的生存期。而全局变量改成静态变量后改变了它的作用域,限制了它的使用范围。static局部变量只初始化一次,下一次依据上一次的结果值。static函数与普通函数的作用域不同,仅在本文件,只在当前文件中使用的函数应该说明为内部函数。static函数在内存中只有一份,普通函数在每个调用中都维持一份拷贝。

1.10 程序的内存分配

  • 栈区(stack):由编译器自动分配释放,存放函数的参数值,局部变量的值,其操作方式类似于数据结构中栈。
  • 堆区(heap):一般由程序员分配释放,若程序员不释放, 程序结束时可能有操作系统回收,它与数据结构中的堆是不同的,其分配方式类似于链表。
  • 全局区(静态区static):全局变量和静态变量的存储是是放在一块的。初始化的全局变量和静态变量放在一块区域,未初始化的全局变量和静态变量放在响铃的另一块区域。
  • 文字常量区:存放常量的字符,程结束后由统释放。
  • 程序代码区:存放函数体的二进制代码。

举例

int a = 0;        //全局初始化区
char *p1;        //全局未初始化区
main()
{
    int b;
char s[] = “abc”;  //栈
char *p2;       //栈
char  *p3 = “123456”;
static int c = 0;   //全局初始化区
p1 = (char *)malloc(10);
p1 = (char *)malloc(10);    //分配分配得来10和20字节区域在堆区
strcpy(p1, “123456”);      //123456\0放在常量区,编译器可能将它与“1223456”优化成一个地方。

} 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

1.11 堆和栈的区别

申请方式

  • 栈:由系统自动分配。

- 堆:由程序员申请,并指明大小。

C:p1 = (char *)malloc(10);
C++:p2 = (char *)malloc(10);
 
 
  • 1
  • 2
  • 1
  • 2

注意:p1和p2本身是在栈中。

申请后系统的响应

  • 栈:只有栈的剩余空间大于申请的空间,系统将为程序提供内存,否则将提示栈溢出。
  • 堆:首先系统中会有一个记录空闲内存地址的链表,系统受到程序的申请时会编立该链表,寻找第一个空间大于所申请的堆结点,并把该结点的空间分配菲程序。同时,系统会在这块内存空间的首地址记录本次分配的大小,这样delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小并不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

1.12 指针数组与数组指针

int(*p)[4],这个就是行指针这种类型的指针p是指向一个一维数组,这个一维数组包含4个整形元素。

但是 int a[4];p=a; 这种方式却是不对的因为p只能指向一个整型的一维数组,不能指向一个整型数据,a所指向的正是a[0],是个整型数。

实际上int(*p)[4]这种类型的指针是用于多维数组中的,比如定义一个二维数组int b[3][4],就可以这样赋值p=&b[0],使p指向一维数组b[0],而且p的增减是以一维数组的长度为单位的,比如p+1指向的就是b[1]了

int *p[4]这个是指针数组了,首先弄明白这个是数组,里面存放的是指针也就是地址,这个地址所指向的是一个整型数据,你可以把p[0],p[1]….当作一个个的指针变量来使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值