作用域 内存布局 static volatile register

函数外定义的是全局变量        ----------> 整个程序都可以访问到,不过不同文件需要extern 
函数内定义的是局部变量

局部变量也分块作用域 :

int  a = 2;

int main()
{
        int a = 5;

        {
            int a = 10;
        }    
}

同一个函数内,子函数也可以访问到内部的变量
  1. #include <stdio.h>
  2. #include <string.h>
  3. int a;
  4. void foo()
  5. {
  6. printf("%d\n", a); //竟然可以输出5
  7. }
  8. int main()
  9. {
  10. a = 5;
  11. foo();
  12. }

  1. #include <stdio.h>
  2. #include <string.h>
  3. int a;
  4. void foo()
  5. {
  6. printf("%d\n", a); //结果输出0,因为他寻找的是全局变量a 全局变量自动初始化为0
  7. }
  8. int main()
  9. {
  10. int a = 5;
  11. foo();
  12. }

  1. #include <stdio.h>
  2. #include <string.h>
  3. void foo()
  4. {
  5. printf("%d\n", a); //报错,因为没有声明
  6. }
  7. int main()
  8. {
  9. int a = 5;
  10. foo();
  11. }

函数挨个调用的特殊现象:

  1. #include <stdio.h>
  2. #include <string.h>
  3. void fun()
  4. {
  5. int a;
  6. printf("%p %d\n",&a ,a);
  7. a = 10;
  8. printf("%p %d\n",&a ,a);
  9. }
  10. int main()
  11. {
  12. fun(); //垃圾值 10
  13. fun(); // 10 10 第二次调用,第一个a应该还是垃圾值,但是fun函数释放的内存刚好被再次使用,所以还是10
  14. }



如果在两次调用函数之间,执行一下其他操作,结果才是正常现象
  1. #include <stdio.h>
  2. #include <string.h>
  3. void fun()
  4. {
  5. int a;
  6. printf("%p %d\n",&a ,a);
  7. a = 10;
  8. printf("%p %d\n",&a ,a);
  9. }
  10. int main()
  11. {
  12. fun(); //垃圾值 10
  13. printf("****\n");
  14. fun(); //垃圾值 10
  15. }



两个文件的话,需要 extern 声明 

a.c     int b = 10;
b.c    extern int b;

static的三个作用:

①限制了作用域
static  int  a               
限制了a只能使用在本文件, 其他文件extern也没用

②延长生命周期
  1. #include <stdio.h>
  2. #include <string.h>
  3. void fun()
  4. {
  5. static int a;
  6. printf("%p %d\n",&a ,a); // 这个地址和局部变量在栈区开辟的地址不一样的地址
  7. a = 10; // static 在 数据段 开辟的空间 和全局变量在的空间一样 就是说程序结束也释放
  8. printf("%p %d\n",&a ,a);
  9. }
  10. int main()
  11. {
  12. fun(); //0 10
  13.                             //不是垃圾值,未初始化的会在Bss区,全局变量也不会是垃圾值,是0,
  14.                             // 在栈区也就局部变量才会出现垃圾值
  15. printf("****\n");
  16. fun(); //10 10
  17. }


③封装了私有数据
static修饰函数,不同文件的函数,无法在调用这个被修饰的函数。

static void fun( void )
{

}
修饰变量也一样。见①。 static已经在编译的时候有值了

内存存储位置介绍:

栈区   高地址到低地址
堆区   低地址到高地址

而针对堆区的内存,一般由程序员进行分配和释放, 使用堆内存的原因一般是“栈上内存比较小,不够用”、“系统管理内存的方式死板,不方便用”这两大类原因。对于堆上的内存,被程序员手动分配后,若程序员不释放就可能会出现“内存泄漏”。很多企业级的应用,都因为内存泄漏而在“正常”运转很长时间后,轰然“坍塌”。


全局区、文字常量区和程序代码区在我们入门阶段,暂时还可以不去过多理解(甚至看不懂也无妨),只需要知道他们的大致作用即可——全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 程序结束后由系统释放;文字常量区是用于储存常量字符串的, 程序结束后由系统释放;程序代码区用于存放函数体的二进制代码。



 命令行参数:

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main(int argc, char * argv[])
  4. {
  5. int i;
  6. printf("%d\n",argc);
  7. for(i = 0; i < argc ; i++)
  8. printf("%s\n",argv[i]);
  9. }



  1. #include <stdio.h>
  2. #include <string.h>
  3. int main(int argc, char * argv[])
  4. {
  5. if(argc < 3)
  6. {
  7. printf("you need args\n");
  8. return -1;
  9. }
  10. int n = atoi(argv[1]);
  11. int i;
  12. for(i=0;i<n;i++)
  13. printf("%s\n",argv[2]);
  14. }


atoi : 把字符串转变成数字(类似于js的parseInt)

1234          ----->      1234
abcd          ----->      0
123abcd    ----->     123
abcd123    ----->      0


const使用介绍:

把变量变成了常量

const int a = 3;      //还是在栈上开辟的地址,可以修改。只是给编译器看的,不可以修改。
a = 5;//错误

int *p = &a;
*p = 5;//可以变

两个等价
const int a
int const a

两个等价
const int *a                       const修饰的是 *a, 表示里面内容不可变,但是a的地址可以变
int const *a


int * const a                    const修饰的是 a, 表示a的地址不可变,   但是里面内容可以改变
const int * const a         a的地址不能变,内容也不可变


如果 const在 * 的前面 就表示约束了*a        即*a不可变  即原来的内容不可改变
如果  *在const的前面   就表示约束不了*a    只是约束了a 表示地址不可变


在函数接口中,很多都使用了const

volatile

防止编译器优化对内存的读写
每次访问被volatile的变量 都需要从内存从新取值

volatile char * ch = (volatile char *)0x8000;
while(*ch)                        //加了volatile每次都向内存取值,不加的话,会放在cpu寄存器,值不变化。
{
    printf("hello\n");
    Sleep(1);
}

register

希望被修饰的变量放到寄存器里 
但不一定放到寄存器里。
寄存器变量不能取其地址





posted @ 2014-09-02 16:25  我爱背单词  阅读(187)  评论(0编辑  收藏  举报