一个C语言程序的分析:运行速度和文件大小以及变量初始值

环境

  • Ubuntu 22.04
  • gcc 11.4.0
  • Window 11
  • Microsoft Visual Studio Community 2022 (64-bit) - Current Version 17.6.2

运行速度

一个C程序 test1.c 如下:

int array[30000][30000];

int main() {
	for (int i = 0; i < 30000; i++)
		for (int j = 0; j < 30000; j++) {
			array[i][j] = 12345;
		}

	return 0;
}

编译:

gcc test1.c -o test1

运行并查看运行时间:

time ./test1
./test1  1.28s user 1.75s system 99% cpu 3.035 total

用时1.28秒。

修改一下代码,把循环里i和j的顺序交换一下:

int array[30000][30000];

int main() {
	for (int j = 0; j < 30000; j++)
		for (int i = 0; i < 30000; i++) {
			array[i][j] = 12345;
		}

	return 0;
}

运行结果如下:

time ./test2        
./test2  15.92s user 1.59s system 99% cpu 17.533 total

可见,运行时间从原先的1.28秒暴涨到15.92秒。

其实,我们能猜到,引起性能下降的原因,一定与数组在内存中的存储方式有关。

以二维数组为例:在C语言中,是按“先列后行”来存储的,也就是按 arr[0][0]arr[0][1]arr[0][2] ,……,arr[1][0]arr[1][1]arr[1][2] ,……这样的顺序连续存储的。

写一个程序来检验如下:

#include <stdio.h>

int arr[3][3];

int main() {
	printf("size of int = %ld\n\n", sizeof(int));

	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++) {
			printf("arr[%d][%d] address: %p\n", i, j, &arr[i][j]);
		}

	return 0;
}

运行结果如下:

size of int = 4

arr[0][0] address: 0x5585c16fb040
arr[0][1] address: 0x5585c16fb044
arr[0][2] address: 0x5585c16fb048
arr[1][0] address: 0x5585c16fb04c
arr[1][1] address: 0x5585c16fb050
arr[1][2] address: 0x5585c16fb054
arr[2][0] address: 0x5585c16fb058
arr[2][1] address: 0x5585c16fb05c
arr[2][2] address: 0x5585c16fb060

可见,int 类型的size是4,而数组中每两个相邻元素,其地址编码相差也是4。

计算机访问连续内存地址的速度,要远远快于非连续地址。这也是数组要比链表访问速度更快的原因。

注:Java程序也类似。

文件大小

全局变量

再来看一下 test1.c

int array[30000][30000];

int main() {
	for (int i = 0; i < 30000; i++)
		for (int j = 0; j < 30000; j++) {
			array[i][j] = 12345;
		}

	return 0;
}

经过编译后,生成的 test1 文件大小为16KB。

ll test1*
-rwxr-xr-x 1 root root 16K 11月 19 19:07 test1
-rw-r--r-- 1 root root 150 11月 19 18:51 test1.c

如果把数组大小改变,编译后的文件大小不变。

这是为什么呢?按理说,array是一个全局变量,是在编译期静态的生成的,应该会占据可执行文件的空间,但这里却似乎并没有影响。

我猜测是因为编译器做了一些优化。虽然声明了全局数组,但是没有赋初值,所以编译器并没有为数组分配空间。

如果有赋初值,则编译后的文件就会随着数组大小而显著变化。

创建文件 test11.c 如下:

int array[300][300] = {123};

int main() {
}

编译后,生成的文件大小为368KB:

ll test11*
-rwxr-xr-x 1 root root 368K 11月 19 20:06 test11
-rw-r--r-- 1 root root   45 11月 19 20:06 test11.c

创建文件 test12.c 如下:

int array[3000][3000] = {123};

int main() {
}

编译后,生成的文件大小为35MB:

ll test12*
-rwxr-xr-x 1 root root 35M 11月 19 20:08 test12
-rw-r--r-- 1 root root  47 11月 19 20:07 test12.c

可见,数组大小扩大100倍,文件大小也扩大了100倍。

局部变量

对于局部变量,是运行期(调用对应函数时)在栈上分配内存的,所以数组大小并不会影响文件大小:

int main() {
	int array[30000][30000] = {123};
}

这里不管数组大小如何变化,编译后生成的可执行文件都是16KB。

未初始化数组的内容

另一个好玩的问题是,如果定义了数组,但没有初始化,那么数组的内容是什么?

全局变量

对于全局变量,其内容会被自动初始化为0。

#include <stdio.h>

int array[300][300];

int main() {
	printf("%d\n", array[5][5]);
}

运行结果如下:

0

这应该是在load可执行文件时,将其内存初始化。

局部变量

#include <stdio.h>

int main() {
	int array[300][300];
	printf("%d\n", array[5][5]);
}

运行结果如下:

0

可见,局部变量的内存也被初始化为0(在调用对应函数,在栈上分配内存时)。

但这不是100%确定的。在MicroSoft Visual Studio下,其运行结果为:

-858993460

在这里插入图片描述

总而言之,变量最好先初始化,再使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/165319.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Windows安装Vmware 虚拟机

目录 一、Vmware 虚拟机介绍 二、Vmware 虚拟机的三种网络模式 2.1桥接模式 2.2仅主机模式 2.3NAT 网络地址转换模式 三、Vmware 虚拟机的安装 一、Vmware 虚拟机介绍 VMware Workstation Pro 是一款可以在个人电脑的操作系统上创建一个完全与主机操作系统隔离的 虚拟机&…

windows pgsql 数据库 数据目录更改

一.先停止postgres服务 cmd命令 services.msc找到服务停止 二.修改注册表 cmd命令 regedit找到路径 \HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\postgresql-x64-13 将“&#xff0d;D”后的目录名修改为新的数据目录位置即可&#xff0c;如果目录路径中含有…

MyISAM和innoDB两种引擎的对比

innoDB 3.23就有了innoDB引擎&#xff0c;5.5成为了默认引擎&#xff0c;支持外键 是一种事务型引擎&#xff0c;可以保证完整提交和回滚 更新、删除比较多的场景&#xff0c;推荐使用innoDB 不过innoDB对内存要求高&#xff0c;因为索引和数据存到一个表了&#xff1b;写操作…

记录:RK3568显示异常。

最近调一个RK3568的新板子&#xff0c;板子其它接口功能都调试ok。可唯独在适配显示时发现&#xff0c;HDMI和MIPI显示均出现异常。当系统启动要进入桌面时候内核就开始报错。 因为这套源码之前在其它的板子上适配过&#xff0c;所以第一反应就是硬件问题或者是那个电压没配置…

[C/C++]数据结构 LeetCode:用栈实现队列

题目描述: 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、pop、peek、empty&#xff09;&#xff1a; 实现 MyQueue 类&#xff1a; void push(int x) 将元素 x 推到队列的末尾int pop() 从队列的开头移除并返回元素int peek() 返…

7个最佳开源免费库存/仓库管理系统(WMS)

库存/仓库管理软件是一种用于帮助企业管理库存、仓储位置和交付过程的软件系统。这种类型的软件对于拥有大量库存和多个仓库的企业非常有用。 库存/仓库管理软件的作用包括以下几个方面&#xff1a; &#xff08;1&#xff09;减少库存节约成本 通过跟踪库存水平和存储位置&…

defer和async

如果两个属性浏览器都不兼容&#xff0c;推荐把<script>标签放到底部 一般情况下&#xff0c;浏览器在解析html源文件时&#xff0c;如果遇到外部的<script>标签&#xff0c;解析过程就会先暂停&#xff0c;这时会对script进行加载&#xff0c;执行两个过程&…

4种经典的限流算法与集群限流

0、基础知识 1000毫秒内&#xff0c;允许2个请求&#xff0c;其他请求全部拒绝。 不拒绝就可能往db打请求&#xff0c;把db干爆~ interval 1000 rate 2&#xff1b; 一、固定窗口限流 固定窗口限流算法&#xff08;Fixed Window Rate Limiting Algorithm&#xff09;是…

矩阵运算_矩阵的协方差矩阵/两个矩阵的协方差矩阵_求解详细步骤示例

1. 协方差矩阵定义 在统计学中&#xff0c;方差是用来度量单个随机变量的离散程度&#xff0c;而协方差则一般用来刻画两个随机变量的相似程度。 参考&#xff1a; 带你了解什么是Covariance Matrix协方差矩阵 - 知乎 2. 协方差矩阵计算过程 将输入数据A进行中心化处理得到A…

element-plus 表格-合并单元格

利用表格:span-method"" 方法实现合并单元格 合并前 合并后 重点代码generateIndexGroups &#xff0c;找到合并的单元格的index号 代码实现如下 <template><h2>实现表格的合并</h2><div><!-- :span-method"arraySpanMethod&quo…

【Python数据结构与算法】——(线性结构)精选好题分享,不挂科必看系列

&#x1f308;个人主页: Aileen_0v0&#x1f525;系列专栏:<<Python数据结构与算法专栏>>&#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 时间复杂度大小比较 1.time complexity of algorithm A is O(n^3) while algorithm B is O(2^n). Which o…

八、Linux关机重启和用户登录注销

1.Linux关机、重启 基本介绍 shutdown -h now 立即进行关机 shutdown -h 1 “hello&#xff0c;1分钟后会关机了”(h&#xff1a;halt) shutdown 默认就是&#xff08;shutdown -h 1&#xff09; shutdown -r now 现在重新启动计算机(r : reboot) halt 关机&#xff0c;作用和…

用向量数据库Milvus Cloud搭建GPT大模型+私有知识库的定制AI助手——PPT大纲助手

随着人工智能技术的不断发展,AI助手在各行各业中扮演着越来越重要的角色。在商业领域,PPT演示是一种常见的沟通方式,而定制化的PPT大纲助手能够极大地提高PPT制作效率和质量。本文将介绍如何利用向量数据库Milvus Cloud搭建GPT大模型和私有知识库,构建一款高效的PPT大纲助手…

计算机系统的层次结构和性能指标

目录 五层结构三个级别语言 计算机性能指标CPU性能指标系统整体的性能指标 五层结构 三个级别语言 编译程序&#xff1a;将高级语言编写的源程序全部语句一次全部翻译成机器语言程序&#xff0c;而后再执行机器语言程序&#xff08;只需翻译一次&#xff09; 解释程序&#xff…

庖丁解牛:NIO核心概念与机制详解 03 _ 缓冲区分配、包装和分片

文章目录 Pre概述缓冲区分配和包装 &#xff08;allocate 、 wrap&#xff09;缓冲区分片 (slice)缓冲区份片和数据共享只读缓冲区 &#xff08;asReadOnlyBuffer&#xff09;直接和间接缓冲区内存映射文件 I/O将文件映射到内存 Pre 庖丁解牛&#xff1a;NIO核心概念与机制详解…

【Hello Go】Go语言异常处理

Go语言异常处理 异常处理error接口panicrecover延时调用错误问题 异常处理 error接口 Go语言引入了一个关于错误处理的标准模式 它是Go语言内建的接口类型 它的定义如下 type error interface {Error() string }Go语言的标准库代码包errors为用户提供了以下方法 package e…

【算法基础】动态规划

背包问题 01背包 每个物品只能放一次 2. 01背包问题 - AcWing题库 二维dp #include<bits/stdc.h> const int N1010; int f[N][N]; int v[N],w[N]; signed main() {int n,m;std::cin>>n>>m; for(int i1;i<n;i) std::cin>>v[i]>>w[i];for…

2024年csdn最新最全的web自动化测试思路及实战

Page Objects 设计模式 Page Objects概念&#xff1a; Page Objects是指UI界面上用于与用户进行交互的对象 pageobjects 设计模式概念&#xff1a; pageobjects 模式是Selenium中的一种测试设计模式&#xff0c;主要是将每一个页面设计为一个Class&#xff0c;其中包含页面中…

AVL树实现

目录 ​编辑 一&#xff0c;AVL树的概念 二&#xff0c;实现AVL树&#xff08;部分&#xff09; 1.AVL树的节点 2.AVL数的插入 1.当根节点为nullptr时要执行如下代码&#xff1a; 2.当根节点不为nullptr时 1.当parent的_bf变为0时&#xff0c;parent之前的_bf的大小就是…

十、Linux运行级别

1.基本介绍 运行级别说明&#xff1a; 0&#xff1a;关机 1&#xff1a;单用户【找回丢失密码】 2&#xff1a;多用户状态没有网络服务 【非常少】 3&#xff1a;多用户状态有网络服务 【最多】 4&#xff1a;系统未使用保留给用户 5&#xff1a;图形界面【Linux一启动自动进入…