编程其实就是面向内存写代码

### 编程思维

1,编程的时候时常想想内存大概的模型已经划分的区域(主要四大区:静态存储区(数据段) 堆 栈 代码段),[数据段可存放静态数据和自由变量]变量 函数等在内存是在哪个区域的,加了修饰词有什么不同;[函数代码存放在代码段。声明的类如果从未使用,则在编译时,会优化掉,其成员函数不占代码段空间。

补充:代码段、数据段、栈是CPU级别的逻辑概念,堆是语言级别的逻辑概念全局变量或静态变量,放在数据段,]

[数据段:数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。]

函数形参存放位置:主函数的是放在堆里面的,临时变量都是放在栈里面的;

2,声明变量去"接住"你获得的数据进行操作;实现你要的功能,不要去管其他东西;会用是一个层次,理解低层实现原理是另外一个层次;

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

内存主要分布:不可访问区、代码段、数据段、堆、栈、内核

①代码段:.text:用于存放用户代码;.init:用于存储系统给每一个程序自动添加的"初始化"代码

②数据段:.bass 专门存储未初始化的静态变量,它们的值会被初始化为0,static int i;.data 专门存储已初始化的静态数据(静态数据:所有全局变量(全局变量默认初始化为0),及static的局部变量).rodata 存放只读数据(用const修饰),比如字符串、字符常量、整形等 char *p = "helloworld"; //"helloworld"只读字符串

③堆:一块自由的内存,用户可以根据自己需求开辟空间大小,内存释放也是由用户自己进行释放(malloc realloc calloc开辟堆空间,释放free)

④栈:它是从0xC0000000往下增长的部分(后进先出),大概8M,专门存放函数局部变量(思考:如何判断栈是往下增长的 //先进入栈的变量在栈底),

栈空间就是指放置程序的局部数据(也就是函数内数据)的内存空间;

全局变量:存放.data当中,如果没有赋值系统默认初始化为0,如果没有被static修饰其它文件可以调用的变量

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

![Paste_Image.png](http://upload-images.jianshu.io/upload_images/2636843-9fa265630237a0a2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

### 一 内存效率相关(常见关键字)

哪些区哪些特点 画图

①static作用(限制变量/函数(静态)的作用域;设置变量的存储域(主动分配内存在堆))

1.全局变量时存储在不变区(静态变量区)但限制作用域;不能被模块外其它函数访问(静态函数类似,也可防冲突);

*静态函数会被自动分配在一个一直使用的存储区,直到退出应用程序实例,避免了调用函数时压栈出栈,速度快很多;内部函数又称静态函数(static修饰,不怕同名)

2.修饰局部变量时变存储区域"栈"为静态存储区(区别auto),代表该内存只被分配一次而且下次调用时仍维持上次的值;

例:函数中定义,static int j = 10; //此时作用等同为全局变量,静态局部变量只初始化一次?->第二次调用不执行

![static修饰.png](http://upload-images.jianshu.io/upload_images/2636843-666f3160852846de.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

static总结 http://blog.csdn.net/damon_hoo/article/details/38903041

1.静态局部变量:静态局部变量始终存在,生存期为整个源程序,作用域和局部变量是一样的,静态局部变量会被自动的初始化为0.

2.静态全局变量:静态全局变量只能在一个文件中使用

3.静态数据成员变量:描述整个类的特征,是整个类的成员,而不是一个对象的成员

static int i;

初始化静态数据成员在类体外进行,而且前面不加static,以免和一般静态变量混淆

一般在cpp里面初始化,格式

int CStudent::num = 0;

4.静态成员函数:属于整个类的成员函数,是整个类的成员,而不是一个对象的成员,它的调用形式可以用对象来调用它,也可以用类的名字来调用它,静态成员函数可以有类名通过::直接调用,但是非静态成员函数只能通过对象名来调用。

静态成员函数没有this指针,可以直接访问该类的静态成员和静态成员函数,而不能直接操作非静态的成员变量和非静态成员函数,如果静态成员函数中要引用非静态成员,则可以通过对象来引用,

②extern 修饰的变量(这里的变量给外部使用)或者函数不仅本文使用,外部文件也可以使用?

温工:extern引用其他文件的函数

③register 数据类型 变量名;//声明寄存器变量

register int i; //i就是一个寄存器变量

1、用register修饰的变量告诉编译器不要优化,运行效率高

2、不一定能100%分配变量为寄存器变量

④C中的宏与C++中的inline关键字声明频繁使用的小函数

~~~~~~~~~~~~~~~~~~~~~~~~~~~~

①②对应静态存储期:static声明的局部变量具有静态存储持续期(static storage duration),或静态范围(static extent).虽然他的值在函数调用之间保持有效,但是其名字的可视性仍限制在其局部域内。静态局部对象在程序执行到该对象的声明处时被首次初始化;

③对应自动存储期(auto):变量在进入声明该变量的程序块时被建立,它在该程序块活动时存在,退出该程序块时撤销

~~~~~~~~~~~~~~~~~~~~~~~~~~~~

⑤synchronized

volatile三种作用:防止编译器优化;不会阻塞线程;解决变量在多个线程之间的可见性

1.与该变量有关的运算,不要进行编译优化,以免出错

⑥inline内联函数 http://www.cnblogs.com/li-hao/archive/2013/03/15/2961713.html

### 二 数组与指针

void型指针不能解引用(目标类型未定),解引用前必须转化为某种具体的指针类型

④const修饰内容不能做任何改变

例子:int *const p = &test1; //保护的是p里的内容,只能在定义里赋值

//p = &test2; p为常量,不能再赋值

const char *p == char const *p(修改*p)

(1)常量指针,不能通过这个指针改变变量的值,但是还是可以通过其他指针的引用或者变量来改变里面的值

(2)常量指针指向的值不能改变,但是这并不意味着指针不能改变,指针可以指向其它变量的

int test1 = 100;

const int *p;

int *pp;

p = &test1; //指针与变量关联

pp = &test1;

test1 = 200; //通过变量改变里面的值

*pp = 70; //通过其他未用const指针来修改里面的值

//*p = 25; //error: assignment of read-only location ‘*p’

printf("*p = %d\\n",*p);

printf("test1 = %d\\n",test1);

char *const p:

(1)指针常量:指针本身是一个常量,不能再指向别的地址

(2) 指针常量里面的地址不能改变,但是地址中保存的值是可以改变的

int test1 = 100;

int test2 = 25;

int *const p = &test1; //保护的是p里的内容,只能在定义里赋值

//p = &test2; p为常量,不能再赋值

test1 =45;

*p = 70;

printf("*p = %d\\n",*p);

printf("test1 = %d\\n",test1);

const *int const p:指向常量的常指针。p里面的内容不可以改变,同时也不能通过*p改变地址指向的内存

⑤数组初始化 数组求长-\\n也算

bzero menset 定义刚好的数组

char buf[50]={0};//50个都为0

char buf[50]={1};//只有第一个为1

特殊定义:

void func1(void);

void func2(void (*p)(void));

typedef void(*fi)(void (*f2)(void));

f1 a ;

意思:上面是一个指针(函数指针),指向返回类型为void,参数是一个函数指针的指针;

![复杂函数指针.png](http://upload-images.jianshu.io/upload_images/2636843-d60cf7ab3042cc65.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![Paste_Image.png](http://upload-images.jianshu.io/upload_images/2636843-ae7bdb1262684956.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

long在32位编译器下是4个字节

?引用传参的效率

⑥typedef重命名

typedef char *p;

p a="hello";//等价于char *a="hello";

⑨inline 必须是在函数定义时修饰函数才有效,如果只是单纯的在声明时加了inline关键字,而在定义时未加则等于没有适用inline关键字

1.使用场景:https://www.cnblogs.com/fnlingnzb-learner/p/6423917.html

//inline提高效率 函数需要短小精悍 看编译器优化处理 编译时替换

inline int add(int x,int y,int z){

return x + y + z;

}//类似template

### 三 分配优化与安全溢出

⑦泄露与溢出

堆栈溢出一般是循环的递归调用导致(或者大数据结构的局部变量)

⑧虚拟机溢出标志-can not write

### 四 内存映射函数

/*#include

void *mmap(void *addr, size_t length, int prot, int flags,

int fd, off_t offset);

addr ----- > 我们所申请的内存空间的起始地址

NULL ----》系统自动分配

length---- >内存空间的大小

port ------>操作权限

PROT_READ 可读

PROT_WRITE 可写

flags------> 共享属性

MAP_SHARED 可以共享

MAP_PRIVATE 私有

fd--------> 硬件设备的文件描述符

offset----》光标偏移量

int munmap(void *addr, size_t length);*/

### 五 编译&优化等级

http://blog.chinaunix.net/uid-25768133-id-3485479.html

__attribute__ ((__packed__))告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,是GCC特有的语法。这个功能是跟操作系统没关系,跟编译器有关,gcc编译器不是紧凑模式的,我在windows下,用vc的编译器也不是紧凑的,用tc的编译器就是紧凑的

### 六 程序启动/运行流程

1.问题:程序开机自启(程序需要root权限才能启动)

#!/bin/bash

sh /home/hwjc/RSA/release2017-02-23/release2017-02-23/install.sh

sh /etc/init.d/mqtt.sh

ifconfig

更改 vi /etc/profile

加至末尾:echo yhn!#!%!^ | sudo -S /home/hwjc/RSA/release2017-02-23/release2017-02-23/init.sh

改完保存退出

输入命令:source /etc/profile 即可


分享到:


相關文章: