内存就是线性结构的字节数组,对于32位平台而言,这个字节数组的大小是2^32=4294967296个字节,地址编号为:00000000-FFFFFFFF,下面我们就来说一说关于c语言运算过程值存储在哪里?我们一起去了解并探讨一下这个问题吧!
c语言运算过程值存储在哪里
内存就是线性结构的字节数组,对于32位平台而言,这个字节数组的大小是2^32=4294967296个字节,地址编号为:00000000-FFFFFFFF。
数据和代码加载到内存,对存储设备的读取是按块(transer block,几个字节、几十、几百、几千个字节不等)进行的。在CPU内部,对数据的处理是以字长为单位进行的。
1 空间局部性与时间局部性Well-written computer programs tend to exhibit good locality. That is, they tend to reference data items that are near other recently referenced data items or that were recently referenced themselves. This tendency, known as the principle of locality, is an enduring concept that has enormous impact on the design and performance of hardware and software systems.
一个编写良好的计算机程序常常具有良好的局部性(locality)。也就是,它们倾向于引用最近引用过的数据项的附近的数据项,或者最近引用过的数据项本身。这种倾向性,被称为局部性原理(principle of locality)。局部性原理是一个持久的概念,对硬件和软件系统的设计和性能都有着极大的影响。
Locality is typically described as having two distinct forms: temporal locality and spatial locality. In a program with good temporal locality, a memory location that is referenced once is likely to be referenced again multiple times in the near future. In a program with good spatial locality, if a memory location is referenced once, then the program is likely to reference a nearby memory location in the near future.
局部性通常有两种不同的形式:时间局部性(temporal locality) 和空间局部性(spatiallocality), 在一个具有良好时间局部性的程序中,被引用过一次的内存位置很可能在不远的将来再被多次引用。在一个具有良好空间局部性的程序中,如果一个内存位置被引用了一次,那么程序很可能在不远的将来引用附近的一个内存位置。
Programmers should understand the principle of locality because, in general, programs with good locality run faster than programs with poor locality. All levels of modern computer systems, from the hardware, to the operating system, to application programs, are designed to exploit locality. At the hardware level, the principle of locality allows computer designers to speed up main memory accesses by introducing small fast memories known as cache memories that hold blocks of the most recently referenced instructions and data items.
程序员应该理解局部性原理,因为一般而言,有良好局部性的程序比局部性差的程序运行得更快。现代计算机系统的各个层次,从硬件到操作系统、再到应用程序,它们的设计都利用了局部性。在硬件层,局部性原理允许计算机设计者通过引人称为高速缓存存储器的小而快速的存储器来保存最近被引用的指令和数据项,从而提高对主存的访问速度。
At the operating system level, the principle of locality allows the system to use the main memory as a cache of the most recently referenced chunks of the virtual address space. Similarly, the operating system uses main memory to cache the most recently used disk blocks in the disk file system. The principle of locality also plays a crucial role in the design of application programs. For example,Web browsers exploit temporal locality by caching recently referenced documents on a local disk. High-volumeWeb servers hold recently requested documents in front-end disk caches that satisfy requests for these documents without requiring any intervention from the server.
在操作系统级,局部性原理允许系统使用主存作为虚拟地址空间最近被引用块的高速缓存。类似地,操作系统用主存来缓存磁盘文件系统中最近被使用的磁盘块。局部性原理在应用程序的设计中也扮演着重要的角色。例如,Web 浏览器将最近被弓]用的文档放在本地磁盘上,利用的就是时间局部性。容量的Web 服务器将最近被请求的文档放在前端磁盘高速缓存中,这些缓存能满足对这些文档的请求,而不需要服务器的任何干预。
Programs that repeatedly reference the same variables enjoy good temporal locality.
重复引用相同变量的程序有良好的时间局部性。
For programs with stride-k reference patterns, the smaller the stride, the better the spatial locality. Programs with stride-1 reference patterns have good spatial locality. Programs that hop around memory with large strides have poor spatial locality.
对于具有步长为k的引用模式的程序,步长越小,空间局部性越好。具有步长为 1 的引用模式的程序有很好的空间局部性。在内存中以大步长跳来跳去的程序空间局部性会很差。
. Loops have good temporal and spatial locality with respect to instruction fetches. The smaller the loop body and the greater the number of loop iterations, the better the locality.
对于取指令来说,循环有很好的时间和空间局部性。循环体越小,循环迭代次数越多,局部性越好。
// C语言是以行优先顺序存储数组。
#define COL 12
int sumArrRows(int(*a)[COL],int r)
{
int i,j,sum=0;
for(i=0;i<r;i )
for(j=0;j<COL;j )
sum = a[i][j]; // 逐行处理,具有良好的局部性
return sum;
}
int sumArrCols(int(*a)[COL],int r)
{
int i,j,sum=0;
for(i=0;i<r;i )
for(j=0;j<COL;j )
sum = a[j][i]; // 逐列处理,空间局部性差
return sum;
}
Organizing memory systems, usually, adopts the technology , known as the memory hierarchy. In general, the storage devices get slower, cheaper, and larger as we move from higher to lower levels.
组织内存系统通常采用被称为内存层次结构的技术。一般来说,随着我们从更高的级别移动到更低的级别,存储设备变得更慢、更便宜、更大。
In general, a cache (pronounced “cash”) is a small, fast storage device that acts as a staging area for the data objects stored in a larger, slower device. The process of using a cache is known as caching (pronounced “cashing”).
一般而言,高速缓存(cache, 读作“cash”)是一个小而快速的存储设备,它作为存储在更大、也更慢的设备中的数据对象的缓冲区域。使用高速缓存的过程称为缓存(caching)。
The central idea of a memory hierarchy is that for each k, the faster and smaller storage device at level k serves as a cache for the larger and slower storage device at level k 1. In other words, each level in the hierarchy caches data objects from the next lower level. For example, the local disk serves as a cache for files (such as Web pages) retrieved from remote disks over the network, the main memory serves as a cache for data on the local disks, and so on, until we get to the smallest cache of all, the set of CPU registers.
存储器层次结构的中心思想是,对于每个k,位于k层的更快更小的存储设备作为位于k 1层的更大更慢的存储设备的缓存。换句话说,层次结构中的每一层都缓存来自较低一层的数据对象。例如,本地磁盘作为通过网络从远程磁盘取出的文件(例如Web 页面)的缓存,主存作为本地磁盘上数据的缓存,依此类推,直到最小的缓存—— CPU 寄存器组。
Data are always copied back and forth between level k and level k 1 in block-size transfer units. It is important to realize that while the block size is fixed between any particular pair of adjacent levels in the hierarchy, other pairs of levels can have different block sizes.
数据总是以块大小为传送单元(transfer unit),在第k层和第k 1 层之间来回复制。虽然在层次结构中任何一对相邻的层次之间块大小是固定的,但是其他的层次对之间可以有不同的块大小。
Figure below shows the general concept of caching in a memory hierarchy. The storage at level k 1 is partitioned into contiguous chunks of data objects called blocks. Each block has a unique address or name that distinguishes it from other blocks. Blocks can be either fixed size (the usual case) or variable size (e. g. , the remote HTML files stored on Web servers). For example, the level k 1 storage in Figure below is partitioned into 16 fixed-size blocks, numbered 0 to 15.
下图展示了存储器层次结构中缓存的一般性概念。第 k 1 层的存储器被划分成连续的数据对象组块(chunk), 称为块(block)。每个块都有一个唯一的地址或名字,使之区别于其他的块。块可以是固定大小的(通常是这样的), 也可以是可变大小的(例如存储在Web 服务器上的远程HTML 文件)。例如,下图中第k 1 层存储器被划分成16 个大小固定的块,编号为0~15。
存储层次结构:
3 编写局部性良好的程序Programs that repeatedly reference the same variables enjoy good temporal locality.
重复引用相同变量的程序有良好的时间局部性。
For programs with stride-k reference patterns, the smaller the stride, the better the spatial locality. Programs with stride-1 reference patterns have good spatial locality. Programs that hop around memory with large strides have poor spatial locality.
对于具有步长为k的引用模式的程序,步长越小,空间局部性越好。具有步长为1的引用模式的程序有很好的空间局部性。在内存中以大步长跳来跳去的程序空间局部性会很差。
. Loops have good temporal and spatial locality with respect to instruction fetches. The smaller the loop body and the greater the number of loop iterations, the better the locality.
对于取指令来说,循环有好的时间和空间局部性。循环体越小,循环迭代次数越多,局部性越好。
4 缓冲4.1 缓存(cache)是存储分层的概念,在存储器层次结构中,高一层的存储设备是低一层的缓存。
4.2 缓冲(buffer)是内存的一块区域,可以分为两类:
4.2.1 用于IO的一块临时内存存储区域,用于IO数据的批量处理。
#include <stdio.h>
int main()
{
char buf[BUFSIZ];
setbuf(stdout, buf); // 以字符数组buf做为输出缓冲区,其大小为BUFSIZ
puts("This is runoob");
fflush(stdout);
int a;
scanf("%d",&a);
fflush(stdin); // The POSIX and C standards explicitly state that
// using fflush on an input stream is undefined behavior
getchar();
return(0);
}
BUFSIZ是STDIO.H中定义的一个宏:
#if defined(_M_MPPC)
#define BUFSIZ 4096
#else /* defined (_M_MPPC) */
#define BUFSIZ 512
#endif /* defined (_M_MPPC) */
4.2.2 在栈上定义的一个局部字符数组,也就是函数内定义的字符数组。
如果字符数组是通过输入来赋值,而输入的长度超过字符数组的长度时,则会出现所谓缓冲区溢出的概念,如果溢出覆盖了函数栈帧的返回地址,而覆盖返回地址的字符是经过特殊设计的,就有可出现所谓缓冲区溢出攻击的情况。
void bufOverflow()
{
char buf[64];
gets(buf); // here is the stack buffer overflow bug
return;
}
更多细节请参考:C|输入输出缓冲区与缓冲区溢出
-End-