定义一个变量:存储类型  数据类型  变量名

存储类型(变量存储的位置):auto、register、static、extern

1、auto:对于局部变量,atuo可以缺省。位置:栈

2、extern:用来声明全局变量(在当前文件被引用,在其他文件中定义);对于函数,extern可以缺省。位置:初始化的全局变量位于数据段,未初始化的位于bss段。

3、register: 用来定义频繁被使用的变量(局部、整形、字符型),位置:寄存器

4、static:同extern可以修饰变量和函数。修饰变量分为静态全局变量和函数体内的静态变量;位置:初始化的全局变量位于数据段,未初始化的位于bss段。

5、const: 保护传参数时,原数据不被修改。位置:局部常量位于栈,全局常量位于代码段。

6、volatile:

7、enum: 应对一个变量可能存在多个值,枚举类型即将变量所有可能的值(枚举值)一一列举出来。

(1)定义枚举类型:“enum 类型名{枚举值1,枚举值2,……,枚举值n}”。

(2)定义枚举变量:“enum 类型名 变量名”,或者“类型名 变量名”。

(3)枚举值是常量、只能将枚举值赋给枚举变量、枚举值可以是有意义的字符串、枚举值默认从0开始递增。

eg:

enum week{Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday};

enum week day1,day2;

day1 = Wednesday;(day1为2)

8、union: 公用体类似结构体可以定义多个成员变量,但与结构体不同的是共用体共享同一段内存空间,即在某一时刻只能存储其中的一个成员。

eg:

union fun1{

char a[10]; //10字节

double b; //8字节

}

fun1占16个字节(double为union中最大的数据类型,根据内存对齐,空间大小要为8的整数倍)

union fun2{

char a; //1字节

double b; //8字节

}

fun2占8字节

union{

int i;

char a[2];

} u;

u.a[0] = 0x39;

u.a[1] = 0x38;

u.i 的值应该为多少呢?

这里需要考虑存储模式:大端模式和小端模式。

大端模式(Big_endian):字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中。

小端模式(Little_endian):字数据的高字节存储在高地址中,而字数据的低字节则存放在低地址中。

union 型数据所占的空间等于其最大的成员所占的空间。对union 型的成员的存取都是相对于该联合体基地址的偏移量为0 处开始,也就是联合体的访问不论对哪个变量的存取都是从union 的首地址位置开始。

判断大端模式:

int checkSystem( )

{

   union check

   {

      int i;

      char ch;

   } c;

   c.i = 1;

   return (c.ch ==1);

}

9、typedef:

#include <stdio.h>

int add(int a , int b){

Return a+b;

}

void main(){

int (*fun)(int) = (int (*)(int) )add;

int r = fun(20); //正确

//int r = fun(20,30,40);  //正确

printf(“%d\n”,r);

}

函数调用后,在栈中为它的参数分配空间,用实参去初始化形参。上面代码,只为第一个参数初始化,第二个参数没有初始化为随机值。

总结:

1、函数执行的时候有自己的临时栈空间。

2、函数的参数就在临时栈中。如果函数传递实参,则用来初始化临时参数变量。

3、参数传递方式:按值传递、按地址传递、按引用传递

4、函数返回:通过参数返回、通过返回值返回。

_stdcall、_cdecl、_fastcall 函数修饰属性,3种调用方式

int  _attribute_((stdcall)) add(int , int);  //linux

int  _stdcall add(int,int); //windows

通过gcc -S查看汇编,可以看出差异。

_cdecl:所有参数从右到左依次入栈,由调用者负责把参数压入栈,最后也是由调用者负责清除栈的内容

_stdcall:所有参数从右到左依次入栈,由调用者负责把参数压入栈,最后由被调用者负责清除栈的内容

1、决定函数参数压栈顺序

2、决定函数栈清空方式

3、windows里将决定了函数的名字转换

Windows中cl编译命令、link连接命令

far、near、huge指针。far指的是16位寻址、far是32位寻址、huge是综合。

虚拟内存:

问题:

#include <stdio.h>

#include <stdlib.h>

main(){

int * a = malloc(4);

*a=9999;

printf(“%p\n”,a);

while(1);

}

#include <stdio.h>

#include <stdlib.h>

main(){

int * a = 第一个程序中开辟空间的地址;

printf(“%p\n”,a);

while(1);

}

问:会不会打印出9999?

结果:出现段错误

#include <stdio.h>

#include <stdlib.h>

main(){

int * p = malloc(0);

*p=9999;

printf(“%d\n”,*p);

}

问:会不会出现段错误

结果:打印9999

一个程序不能访问另外一个程序的地址指向的空间。

1、每个程序的开始地址都是0x080084000

2、程序中使用的地址都是逻辑地址,仅仅是个编号,用int来表示(32位机,寻址空间4G)。

3、每个程序提供了4G访问能力

4、逻辑地址与物理地址进行关联才有意义,这个过程称为内存映射

5、虚拟内存的提出,禁止用户直接访问物理地址,有助于系统的稳定。

6、以4K(16进制1000)为基本单位进行映射,称为内存页。需要分配4个字节,也会映射4K的空间。

段错误:无效访问,访问超出了该进程所能访问的空间。

非法访问:比如malloc分配的空间之外的空间可以访问,但是非法访问。

虚拟内存分配:

栈:编译器自动生成代码负责维护

堆:地址是否映射,映射的空间是否被管理

1、brk/sbrk  内存映射函数

int brk(void * end);

void *sbrk(int size);

#include <stdio.h>

#include <unistd.h>

void main(){

int *p = sbrk(4); //分配4个字节空间

*p = 8888;

printf(“%d\n”,*p);

}

#include <stdio.h>

#include <unistd.h>

void main(){

int *p = sbrk(0); //虚拟地址的首地址

*p = 8888;

printf(“%d\n”,*p);

}

结果:段错误

#include <stdio.h>

#include <unistd.h>

void main(){

int *p = sbrk(0); //虚拟地址的首地址

brk(p+1);

*p = 8888;

printf(“%d\n”,*p);

}

结果:没问题

#include <stdio.h>

#include <unistd.h>

void main(){

int *p = sbrk(0); //虚拟地址的首地址

brk(p+1);

*p = 8888;

brk(p);

*p = 999;

printf(“%d\n”,*p);

}

结果:段错误

应用:

1、sbrk分配空间

2、sbrk得到没有映射的虚拟地址

3、brk分配空间

4、brk释放空间

sbrk与brk后台系统维护一个指针,指针默认是null。

调用sbrk,判定指针是否是0,是:返回空闲首地址(空间为4K的倍数)初始化该指针,并且把指针位置+size。否:直接返回指针,并且把指针位置+size

sbrk控制起始端

brk控制末端

应用案例:

写一个程序查找1-10000之间所有的素数。并且存放到缓冲,然后打印

缓冲的实现使用sbrk/brk

对比:

new、malloc、brk/sbrk、stl、智能指针

异常处理:

int brk(void *)

void * sbrk(int)

如果成功:brk返回0,sbrk返回指针

如果失败:brk返回-1,sbrk返回(void*)-1

unix函数出错以后,修改内部变量:errno

#include <errno.h>

输出错误原因:

(1)perror  #include<stdlib.h> 参数 s 所指的字符串会先打印出,后面再加上错误原因字符串

范例

#include<stdio.h>

intmain(void){

FILE*fp;

fp=fopen("/root/noexitfile","r+");

if(NULL==fp){

perror("/root/noexitfile");

}

return0;

}

运行结果

[root@localhost io]# gcc perror.c

[root@localhost io]# ./a.out

/root/noexitfile: No such file or directory

(2)printf(“%m”);

(3)首先extern int errno  然后 printf(“%s”,strerror(errno));

Linux--变量与虚拟内存的更多相关文章

  1. Linux进程的虚拟内存区域划分

    Linux进程的虚拟内存区域分为:代码区.只读常量区.全局区.BSS段.堆区.栈区 代码区:存储功能代码,函数名所在的区域 只读常量区:存放字符串常量,以及const修饰的全局变量 全局区/数据区:存 ...

  2. linux变量心得

    前一段时间学习了一下linux的变量,现在总结有3点需要特别注意: linux变量和C/C++变量的区别 linux变量的引用 linux变量特有的命令替换 先说第一点,linux变量更像是宏定义,只 ...

  3. linux --> Linux变量之$#, $*, $@含义

    Linux变量之$#, $*, $@含义 一.介绍 $# //是传给脚本的参数个数 $ //是脚本本身的名字 $1 //是传递给该shell脚本的第一个参数 $ //是传递给该shell脚本的第二个参 ...

  4. Linux系统实现虚拟内存有两种方法:交换分区(swap分区)和交换文件

    Linux系统实现虚拟内存有两种方法:交换分区(swap分区)和交换文件 交换文件 查看内存:free -m , -m是显示单位为MB,-g单位GB 创建一个文件:touch /root/swapfi ...

  5. Linux进程的虚拟内存

    简介 用户进程的虚拟地址空间是Linux的一个重要的抽象:它为每个运行进程提供了同样的系统视图,这使得多个进程可以同时运行,而不会干扰到其他进程内存中的内容. 每个应用程序都有自己的线性地址空间,与所 ...

  6. 为linux系统添加虚拟内存swap分区

    阿铭linux学习笔记之swap分区 一.作用: swap分区是交换分区,在系统物理内存不足时与swap进行交换,对web服务器的性能影响极大,通过调整swap分区大小来提升服务器的性能,节省资源费用 ...

  7. Linux设置Swap虚拟内存方法

    linux可以文件或者分区来当作虚拟内存. 首先查看当前的内存和swap 空间大小(默认单位为k, -m 单位为M): free -m 查看swap信息,包括文件和分区的详细信息 swapon -s或 ...

  8. Java程序在Linux上运行虚拟内存耗用很大

    突然集群的2个节点挂了,通过top查看, 虚拟内存22G, 通过 pmap -x 8 | grep anon 一大堆64M Linux下glibc的内存管理机制用了一个很奇妙的东西,叫arena.在g ...

  9. Linux记录-Linux Swap分区虚拟内存相关解决方案

    Swap用途:Swap意思是交换分区,通常我们说的虚拟内存,是从硬盘中划分出的一个分区.当物理内存不够用的时候,内核就会释放缓存区(buffers/cache)里一些长时间不用的程序,然后将这些程序临 ...

  10. Linux变量及运算

    变量赋值:var=var_value 变量引用:$var 算术运算:var=`expr $var1 + $var2` 字符串连接:var=str$var1 数值比较:-eq/-ne/-gt/-lt/- ...

随机推荐

  1. NULL, '\0',0 '0'的区别

    如题,在程序中经常遇到NULL,和'\0',常常疑惑它们是什么关系,其实它们的值是一样的,只不过表现的形式不一样: 1.NULL; NULL 即空指针,在C和C++中的形式不一样,msdn上有如下的内 ...

  2. arm linux kernel 从入口到start_kernel 的代码分析

    参考资料: <ARM体系结构与编程> <嵌入式Linux应用开发完全手册> Linux_Memory_Address_Mapping http://www.chinaunix. ...

  3. 100%会用到的angularjs的知识点【新手可mark】

    前言:下面我将整理出100%会到的angularjs的知识点,掌握这些知识点你基本上就可以独立完成一个angularjs的项目,前提是你有一定web开发的经验:1.了解基本的javascript的概念 ...

  4. Mispelling4

    Problem Description Misspelling is an art form that students seem to excel at. Write a program that ...

  5. 【Android 界面效果41】Matrix 与 ColorMatrix

    Matrix: 简单用法就是直接使用它的setXX()方法 而高级一点来理解他就是去理解一个线性矩形 首先我们来认识线性矩形:(用画图粗略地画不要见怪) 分析: 那还有一组 MRERSP_0 MRER ...

  6. Android 珍藏(二)

    一.如何控制Android  LED等?(设置NotificationManager的一些参数) 代码如下: final int ID_LED=19871103; NotificationManage ...

  7. emWin使用外部SRAM的方法

    我用的是stm32,加了1MB的外部SRAM,在使用emWin的时候,将一部分内存分配给emWin使用.其实方法很简单,传入SRAM数据总线地址即可,数据位宽我采用16bit,因为使用的SRAM是16 ...

  8. 剑指Offer32 丑数

    /************************************************************************* > File Name: 32_UglyNu ...

  9. 有一种风格,叫做 Low Poly 3D

    原作:Simon阿文    杂交编辑者:RhinoC       个人更推崇使用第二款神器 ImageTriangulator :http://www.conceptfarm.ca/2013/port ...

  10. UIScrollView的相关属性说明

    _scrollView = [[UIScrollView alloc] init]; //height = 0:禁止垂直方向滚动 _scrollView.contentSize = CGSizeMak ...