7.31 作用域 内存布局 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


希望被修饰的变量放到寄存器里

但不一定放到寄存器里。

寄存器变量不能取其地址

来自为知笔记(Wiz)

时间: 2024-08-30 12:12:02

7.31 作用域 内存布局 static volatile register的相关文章

C语言中关键字auto、static、register、const、volatile、extern的作用

原文:C语言中关键字auto.static.register.const.volatile.extern的作用 关键字auto.static.register.const.volatile.extern 这些关键词都是c++基础知识,我整理了一下,希望对新学的朋友们有用: (1)auto 这个这个关键字用于声明变量的生存期为自动,即将不在任何类.结构.枚举.联合和函数中定义的变量视为全局变量,而在函数中定义的变量视为局部变量.这个关键字不怎么多写,因为所有的变量默认就是auto的. (2)reg

C语言-第31课 - 程序的内存布局

第31课 - 程序的内存布局 代码在可执行程序中有如下的对应关系 有初始值的放在data段,没有初始的放在bss段.静态存储区就对应了这两个区域. 我们写的函数,可移执行的代码段,放在text段. 这里并不见堆和栈的踪影,因为这只是我们的可执行文件的布局,并不会我们执行起来,进程的布局,所以是看不到堆和栈的. 文件布局在内存中的映射 高地址内存 File header 栈 .text 堆 .data .bss .data .bss .text 未映射区域 a.out a.out进程的地址空间 当

Qemu对x86静态内存布局的模拟

快乐虾 http://blog.csdn.NET/lights_joy/ [email protected] 本文适用于 QEMU-0.10.5 VS2008 欢迎转载,但请保留作者信息 在PC机中,由于早期版本的系统资源限制,其物理内存被分为多个不同的区域,并一直延续至今,那么QEMU是如何对这种静态内存布局进行模拟的呢? 1.1    整体内存分配 虽然PC机的物理内存被人为地分为多个不同的区域,但是在物理结构上它们仍然是连续的,因此qemu直接从宿主机中分配了一块内存: int main(

JVM(二)JVM内存布局

这几天我再次阅读了<深入理解Java虚拟机>之第二章"Java内存区域与内存溢出异常",同时也参考了一些网上的资料,现在把自己的一些认识和体会记录一下.  (本文为博主原创文章,转载请注明出处) 一.概述 在网上看到很多的各种文章来写Java内存布局/Java内存模型(JMM)/Java内存分配和回收等.初学者,往往容易被搞混淆,这些东西到底都是些啥?讲的是不是同一个东西?如果不是同一个东西,那它们之间又有什么区别和联系?说句实话,笔者在看到这些文章和概念时,一样是有这些疑

C、C++变量auto,static,register,extern类型

auto: 推导类型变量:/Zc:auto[-] compiler option tells the compiler how to use the auto keyword to declare variables.' data-guid="0be6182f1ca27bd1ea991f3f06584d3b">编译器选项指示编译器如何使用 auto 关键字来声明变量. /Zc:auto, the compiler deduces the type of the declared

UNIX高级环境编程(8)进程环境(Process Environment)- 进程的启动和退出、内存布局、环境变量列表

在学习进程控制相关知识之前,我们需要了解一个单进程的运行环境. 本章我们将了解一下的内容: 程序运行时,main函数是如何被调用的: 命令行参数是如何被传入到程序中的: 一个典型的内存布局是怎样的: 如何分配内存: 程序如何使用环境变量: 程序终止的各种方式: 跳转(longjmp和setjmp)函数的工作方式,以及如何和栈交互: 进程的资源限制 ? 1 main函数 main函数声明: int main (int argc, char *argv[]); 参数说明: argc:命令行参数个数

Java内存模型与volatile

内存模型描述的是程序中各变量(实例域.静态域和数组元素)之间的关系,以及在实际计算机系统中将变量存储到内存和从内存取出变量这样的低层细节. 每一个线程有一块工作内存区,其中保留了被所有线程共享的主内存中的变量的值的拷贝.为了存取一个共享的变量,一个线程通常先获取锁定并且清除它的工作内存区,这保证该共享变量从所有线程的共享内存区正确地装入到线程的工作内存区,当线程解锁时保证该工作内存区中变量的值写回到共享内存中. 下面简单给出了规则的重要推论:1. 适当运用同步结构,能够正确地把一个或一组值通过共

C++类内存布局图(成员函数和成员变量分开讨论)

一.成员函数 成员函数可以被看作是类作用域的全局函数,不在对象分配的空间里,只有虚函数才会在类对象里有一个指针,存放虚函数的地址等相关信息. 成员函数的地址,编译期就已确定,并静态绑定或动态的绑定在对应的对象上.对象调用成员函数时,早在编译期间,编译器就可以确定这些函数的地址,并通过传入this指针和其他参数,完成函数的调用,所以类中就没有必要存储成员函数的信息. 二.成员变量 转自:http://www.cnblogs.com/jerry19880126/p/3616999.html 书上类继

黑马-----内存模型和volatile详解

黑马程序员:Java培训.Android培训.iOS培训..Net培训 JAVA线程-内存模型和volatile详解 一.单核内存模型 1.程序运行时,将临时数据存放到Cache中 2.将CPU计算所需要的数据从Cache中拷贝一份到H Cache中 3.CPU直接从H Cache中读取数据进行计算 4.CPU将计算的结果写入H Cache中 5.H Cache将最新的结果值涮入Cache中(何时写入不确定) 6.将Cache中结果数据写回程序(如果有需要,例如文件.数据库) 需要H Cache