基础回顾之存储类、链接与内存管理

做技术,越做到后面越觉得基础的、底层的才是越需要巩固的。最近做的项目有关音视频、图像处理,涉及到的都死c和c++相关的代码。遇到了问题才发现,c和c++才是通用大法。这两块没学好,那也只有玩一玩应用层、UI这些东西。抽空整理下!

作用域

四种:

  • 多个文件共享的变量
  • 特定文件每个函数共享的变量
  • 某个函数特有的变量
  • 某个函数一个代码块的变量

一个C变量的作用域可以是代码块作用域,函数作用域,文件作用域,基本概念就不说了。

需要注意的几点:

for (int i = 0; i < 10 ; i++) {
        printf("%d", i);
    }

这里i的作用域是整个for循环。

一个所有函数之外定义的变量就是文件作用域。整个文件可以访问该变量。也叫全局作用域

#include "CTest.h"
int a = 4;

int main() {
    for (int i = 0; i < 10 ; i++) {
        printf("%d", i);
    }
    printf("%d", a);
    return 0;
}

int test() {
    a = 6;
    printf("%d", a);
    return a;
}

链接

  • 外部链接:多个文件使用
  • 内部链接:当前文件使用
  • 空连接:函数代码块使用
int a = 4; // 外部链接
static int b = 5; // 内部链接、文件私有
int main() {
    ...
    return 0;
}

存储时期(变量在内存中生存的时间)

  • 静态存储:程序执行期间一直存储,文件作用域(内部和外部)的变量具有静态存储时期。文件作用域中特别注意用static表明链接类型而并非存储时期。一个使用了static生命的文件作用域变量表示这个变量具有内部作用域。
  • 自动存储:代码块作用域的变量。

5种存储类:自动,寄存器,代码作用域静态,外部静态,内部静态。下面这种表总结了上面的多种情况。

重点说明一下寄存器变量:寄存处变量是存储在CPU的寄存器中,比一般的内存要快很多。但是有一个问题就是寄存器变量的地址是无法获取的。

把变量定义下所有函数之外,就创建了一个外部变量,为了使程序清晰,可以在使用使用外部变量的函数中通过extern来再次声明。如果变量在别的文件定义,使用extern来声明就是必须的。这里想一想OC中的写第三方库的时候,为了让其他模块能够访问某个变量就是通过这种方式来达到目的的。

比如YYWebImageSetter中。
.h

extern NSString *const _YYWebImageFadeAnimationKey;
extern const NSTimeInterval _YYWebImageFadeTime;
extern const NSTimeInterval _YYWebImageProgressiveFadeTime;

.m

NSString *const _YYWebImageFadeAnimationKey = @"YYWebImageFade";
const NSTimeInterval _YYWebImageFadeTime = 0.2;
const NSTimeInterval _YYWebImageProgressiveFadeTime = 0.4;

函数也是具有存储类。函数默认是外部的,可以被其他文件中的函数调用,静态函数只可以在定义它的文件中使用(用static)

使用static可以防止名字的冲突,为文件定义一个私有的变量或者函数。想想平时我们在定义常量的时候,有时候会出现冲突,OC中用static解决的。应该有些同学有印象的。

分配内存

系统自动分配内存:

float x;
char hello = "hello world";

系统将会预留出存储float或字符串的足够内存空间。也可以指定预留多少内存空间:

int plates[100];

声明了100个内存位置,每个位置可以存储一个int值。这里的plate和上面的x、hello变量可以理解为内存的标识符。所以我们可以用x、hello来标识、获取这些内存数据。

malloc&&free&&calloc

用于动态开辟内存。函数void* malloc( size_t size );

函数说明

Allocates size bytes of uninitialized storage.
If allocation succeeds, returns a pointer to the lowest (first) byte in the allocated memory block that is suitably aligned for any object type.
If size is zero, the behavior is implementation defined (null pointer may be returned, or some non-null pointer may be returned that may not be used to access storage, but has to be passed to free).

malloc is thread-safe: it behaves as though only accessing the memory locations visible through its argument, and not any static storage.
A previous call to free or realloc that deallocates a region of memory synchronizes-with a call to malloc that allocates the same or a part of the same region of memory. This synchronization occurs after any access to the memory by the deallocating function and before any access to the memory by malloc. There is a single total order of all allocation and deallocation functions operating on each particular region of memory.

传入所需要的内存字节数,然后malloc找到内存中一个大小适合的快,内存是匿名的,不像上面可以用定义float x;x用于标识。不过返回的是一个开辟内存的第一个字节的地址。虽然没有为它指定名字,但是我们可以通过指针来接受返回的值来访问那块内存。

因为char代表一个字节,所以经常将malloc定义为指向char的指针类型。但是后来又了新的类型——————通用型指针(void *)。这样就可以返回其他类型的了。特别注意如果malloc找不到所需的空间,就会返回空指针。比如传入一个负数就会返回NULl

double *dbl;
dbl = malloc(30 * sizeof(double));

请求30个double类型值的空间,并把dbl指向该空间的所在的起始位置。然后就可以使用数组那样使用它。简单来讲可以dbl[0],dbl[1]访问

开辟了内存,必定要释放内存。用free释放内存。对应到OC就是那句内存管理的至理名言谁开辟、谁释放(alloc、release)

一次malloc,应该调用一次free。free的参数是malloc返回的地址,释放掉先前分配的内存。不能使用free来释放通过其他形式分配的内存,比如声明一个数组。

例子强调一下free的重要性

void memoryTest() {
    double array[2000];
    for (int i = 0; i< 1000; i++) {
        testCopy(array, 2000);
    }
    
}

void testCopy(double arr[], int count) {
    double *temp = (double *)malloc(count * sizeof(double));
    
    // No free
}

第一次调用testCopy,创建指针temp,并使用malloc开辟了2000 * 16,一个32000个字节。当函数终止,temp作为自动变量被销毁,但是它指向的32000个字节的内存仍然存在,并且无法访问这些内存,因为地址不见了(temp销毁),由于没有调用free,那么就不可以再次使用这些内存。

第二次调用testCopy,又创建一个temp,但是第一次的32000字节的块已经不能再用了。所以malloc不得不再去开辟一块新的内存地址。当函数终止,这块内存同样没有调用free,创建的内存同样不能被访问。

循环1000次,就是32000000个字节。已经有3200万字节在内存中中不能使用。这就是在做iOS开发中MRC时代经常遇到的内存泄漏。

为了说明问题,这里我用xcode测试了一下,把循环次数改为了100000000。

  • 没有加free之前。


  • 加free之后。


对比上面很明显能看到两者的区别。

calloc与malloc最大的区别是calloc会把开辟的全部位置为0。使用方式和malloc类似,同样需要用free释放内存。

long *test;
test = (long *)calloc(100, sizeof(long));

开辟了可以容乃100个long类型的内存空间。

常见的限定词

const

普通类型前,标识这个值不可变。而用在指针的时候情况就分多种了

因为指针存在,指针不可变还是指向的值不可变。

  • const float *pf(等同于float const * pf):表示pf指向一个常量浮点型数值。但是pf本身的值可以改变。比如它可以指向另一个const值
  • float * const pt:表示pt是一个常量指针,他总是指向同一个地址,但是地址里面的内容可以改变。
  • const float * const pfc:表示pfc是个常量指针,而且指向的地址内容也不能变。

记忆方式,const位于*左边代表指向的值不可变,位于*右边指针不可变

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,888评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,677评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,386评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,726评论 1 297
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,729评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,337评论 1 310
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,902评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,807评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,349评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,439评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,567评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,242评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,933评论 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,420评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,531评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,995评论 3 377
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,585评论 2 359

推荐阅读更多精彩内容