前言

最近用C刷PAT算法题目, 发现C语言有太多需要关注大小范围的东西必须

知道, 虽说挺麻烦, 但也挺有意思.

int最大值是多少

首先就是int类型的取值范围, 这个太常用. C语言标准规定最低范围是

[-2^16 + 1, 2^16], 即[-65535, 65536], 但这个明显已经过时, 目前

绝大部分机器支持的int范围是[-2^32 + 1, 2^32], 也就是正负20个亿

左右, 因此大家刷题的时候只要整数范围是在20亿这个量级, 就可以大胆的

使用int, 不必动用long int, long long int等. 更多关于C语言

自带数据类型极限, 以及在自己本地测试数据类型极限, 可以访问

这里

1000万的整型数组能不能运行

如果我们直接在C程序main函数中开个1000万的整型数组, 运行这个程序会发生

什么 ?

#include <stdio.h>

int main() {
int arr[10000000]; // 1000万
arr[400] = 123;
printf("%d\n", arr[400]);
return 0;
}

在win10_64位 CodeBlock 16.01下运行结果:

在win10_64位 gcc6.3.0(MinGW)命令行编译运行结果:

可以看到, 在IDE中运行程序直接崩溃, 在命令行中什么也没输出,

总之就是程序运行不正常, 可以理解为内存爆掉了. 难道C语言连

1000万的整型数组都开不出来吗?

举个例子:若果大家经常刷算法题应该有这个经验很多时候用一个

非常大的数组解题会显著提高效率, 非常方便. 比如输入100万

个数, 每个数都不大于10万, 然后任意给你一个数, 问你这个数存

不存在, 也就是查找, 若果按照传统的方法就算用C语言自带的2分

查找法, 每次在100万个数据中找出一个数, 工作量依旧非常巨大,

而且效率低下, 而直接把输入的数据当数组下标开个10万的数组解决,

问题则非常简单. 说到这里相信懂的人已经懂了, 如果不知所云也没

关系, 继续刷题, 以后回过头来看.

当我们谈C语言内存的时候我们再谈什么

大家可能都能听过什么栈内存, 堆内存, 什么堆栈, 静态内存, 动态内存

等等, 一些概念, 乍一看一脸懵逼, 这些都什么玩意, 我们现在先不关注

概念的东西, 直接看实际需求.

上面我们已经提到, 在main函数中开个1000万的整型, 程序就爆掉了, 那

到底, 最大能开多大的容量的整型数组, 才能不爆掉呢. 首先我们先来一波

计算, 大部分机器sizeof(int)得到的值是4, 也就是一个整型数据

需要4个字节的容量, 1000万个整型数组需要4 * 10000000 / 1024 / 1024,

计算结果大约是38M

1G = 1024M, 1M = 1024K, 1K = 1024byte(字节)

在Linux或者是在windows下的mingw环境下, 可以输入命令ulimit -a, 查看

C语言内存分配情况, 在下图我的机器上可以看到stack size大约为2M

按照一个整型数据占4个字节来算, 2M内存用来开数组, 最大也就开个52万左右,

我们的测试开了1000万, 显然是要爆掉的. 那么问题来了, 难道我们的C语言,

就TM只能提供区区50来万的数组空间吗? 别说50万, 就是1千万, 也不一定完全

够用呀. 当然不是, 上面只是C语言分配内存的默认方法, 也是最简单的方法,

这种方法用的是栈内存, 而C语言能提供的栈内存非常有限, 顶天就那么几M,

如果需要拿到更大的内存空间, 就不能使用这种方法了.

若果大家觉得52万, 貌似已经够自己用了, 我只能说, 兄弟再刷两题看看

栈和堆栈意思一样, 堆是另一种数据结构

我就是需要需要很大的内存空间怎么办

第1种方法: 使用malloc

这种方法我在这里不展开细说了, 如果大家对malloc很熟的话, 我这么

一提大家应该就明白了. 最简单的用法就是用malloc分配数组空间

#include <stdio.h>
#include <stdlib.h> int main() {
int *arr;
arr = (int*)malloc(10000000 * sizeof(int));
arr[400] = 200;
printf("%d\n", arr[400]); // 正常输出 200
free(arr);
return 0;
}

第2种方法: 把变量声明放到文件作用域中(或者叫全局作用域)

这种方法重点推荐使用, 简单粗暴非常方便, 什么叫文件作用域就是把

变量声明挪到所有函数之外, 也就是main函数的上面即可. 源代码几乎

不用作任何改动, 直接把大数据变量声明搬到main函数上面即可.

#include <stdio.h>
#define LEN 24 long long int arr[1 << LEN]; // 声明放到这里就对啦 int main() {
for (long long int i = 0; i < (1 << LEN); i++) {
arr[i] = i + 200;
printf("i: %d\n", i);
}
return 0;
}

1 << 24相当于1000000000000000000000000(24个0), 也就是2^24 = 16777216

下面是我机器的运行结果, 注意运行时间可能会非常长

可以看到, 即便是开出1600万, 这么大的数组, 程序依旧能够正常运行.

总结

C语言的内存分配模式大致分为3种

  1. 自动分配. 也就是写在main函数或其它函数里面的, 使用的是栈内存,

    一般栈内存只有几M, 所以这种方法, 分配的整型数组空间可能只有

    几十万, 一般建议刷算法题的时候, 超过10万就不用这种方法
  2. 使用malloc分配, 可以分配的很大, 一般是几个G
  3. 把声明放在全局作用域中, 可以分配的很大, 一般是几个G

参考

【C语言编程】五大内存分区

warning: left shift count >= width of type

转:C语言申请内存时堆栈大小限制

C Primee Plus 第6版 中文版 2016.4出版 Stephen Prata著 姜佑译

C语言可以分配的最大内存的更多相关文章

  1. 《C语言中分配了动态内存后一定要释放吗?》

    问:比如main函数里有一句 malloc(),后面没有free()1.那么当main结束后,动态分配的内存不会随之释放吗?2.如果程序结束能自动释放,那么还加上free(),是出于什么考虑? 答: ...

  2. 【ZZ】C 语言中的指针和内存泄漏 & 编写高效的C程序与C代码优化

    C 语言中的指针和内存泄漏 http://www.ibm.com/developerworks/cn/aix/library/au-toughgame/ 本文讨论了几种在使用动态内存分配时可以避免的陷 ...

  3. c语言类型修饰符及内存

    今天来学习一下c语言类型修饰符及内存分布 1.auto int a; 默认在内存 2.register int a; 限制变量定义在寄存器上的修饰符 编译器会尽量安排CPU的寄存器去存放这个a,如果寄 ...

  4. (转)java内存分配分析/栈内存、堆内存

    转自(http://blog.csdn.net/qh_java/article/details/9084091) java内存分配分析/栈内存.堆内存 java内存分配分析 本文将由浅入深详细介绍Ja ...

  5. C语言笔记 12_可变参数&内存管理&命令行参数

    可变参数 有时,您可能会碰到这样的情况,您希望函数带有可变数量的参数,而不是预定义数量的参数.C 语言为这种情况提供了一个解决方案,它允许您定义一个函数,能根据具体的需求接受可变数量的参数.下面的实例 ...

  6. C语言中储存类别和内存管理

    C语言中储存类别和内存管理 储存类别 C语言提供了多种储存类别供我们使用,并且对应的有对应的内存管理策略,在了解C中的储存类型前,我们先了解一下与储存类型相关的一些概念. 1. 基础概念 对象:不同于 ...

  7. SQL SERVER 内存分配及常见内存问题 简介

    一.问题: 1.SQL Server 所占用内存数量从启动以后就不断地增加: 首先,作为成熟的产品,内存溢出的机会微乎其微.对此要了解SQL SERVER与windows是如何协调.共享内存.并且SQ ...

  8. 怎样给WordPress分配更多的内存

    WordPress如果内存不够,你在操作的时候,就会碰到像这样的问题”Allowed memory size of xxxxxx bytes exhausted”(允许的内存 xxxx 字节已经用光了 ...

  9. C语言中计算变量占用内存空间

    C语言中计算变量占用内存空间 在C语言中通常用[sizeof]运算符计算变量占内存空间,如下面的例子:

随机推荐

  1. KMP + 求最小循环节 --- HDU 1358 Period

    Period Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=1358 Mean: 给你一个字符串,让你从第二个字符开始判断当前长度 ...

  2. 10个 jQuery 小技巧

    10个 jQuery 小技巧 -----整理by: xiaoshuai 1. 返回顶部按钮 可以利用 animate 和 scrollTop 来实现返回顶部的动画,而不需要使用其他插件. // Bac ...

  3. Discretized Streams, 离散化的流数据处理

    Discretized Streams: An Efficient and Fault-Tolerant Model for Stream Processing on Large Clusters   ...

  4. 【BZOJ】1651: [Usaco2006 Feb]Stall Reservations 专用牛棚(线段树/前缀和 + 差分)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1651 很奇妙.. 我们发现,每一时刻的重叠数选最大的就是答案.... orz 那么我们可以线段树维护 ...

  5. (转)word尾注引文添加方式及相关问题

    word引文添加方式:http://www.office68.com/word/word-reference-add.html word通配符:http://www.3lian.com/edu/201 ...

  6. 经典SQL面试题(转)

    http://www.cnblogs.com/kcher90/archive/2013/03/13/2957932.html 有三个表,如果学生缺考,那么在成绩表中就不存在这个学生的这门课程成绩的记录 ...

  7. sdut 2153:Clockwise(第一届山东省省赛原题,计算几何+DP)

    Clockwise Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 Saya have a long necklace with ...

  8. sql server函数(isnull,charindex,cast,自定义函数)

    SELECT charindex( CAST ( dbo.ufn_IsNullOrEmpty ('109722A3-622D-4FD4-A060-0287C933A89E', a.OUID) AS V ...

  9. cocos2dx游戏--三国关羽传【角色扮演类】Demo的制作及实现

    项目地址:https://github.com/moonlightpoet/GuanYuZhuan 主要类及其对应效果: MainScene:菜单界面(用于选择不同剧本) StoryScene:故事界 ...

  10. Zabbix-3.0.3使用自带模板监控MySQL

    导读 Zabbix是一款优秀的,开源的,企业级监控软件,可以通过二次开发来监控你想要监控的很多服务,本文介绍使用Zabbix自带的模板监控MySQL服务. 配置userparameter_mysql. ...