c 内存对齐
当在C 中定义了一个结构类型时,它的大小是否等于各字段(field) 大小之和?编译器将如何在内存中放置这些字段?ANSI C对结构体的内存布局有什么要求?而我们的程序又能否依赖这种布局?这些问题或许对不少朋友来说还有点模糊,那么本文就试着探究它们背后的秘密。
首先,至少有一点可以肯定,那就是ANSI C 保证结构体中各字段在内存中出现的位置是随它们的声明顺序依次递增的,并且第一个字段的首地址等于整个结构体实例的首地址。比如有这样一个结构体:
struct vector
{int x,y,z;} s;
int *p,*q,*r;
struct vector *ps;
p = &s.x;
q = &s.y;
r = &s.z;
ps = &s;
assert(p < q);
assert(p < r);
assert(q < r);
assert((int*)ps == p);
// 上述断言一定不会失败
这时,有朋友可能会问:" 标准是否规定相邻字段在内存中也相邻?" 。 唔,对不起,ANSI C 没有做出保证,你的程序在任何时候都不应该依赖这个假设。那这是否意味着我们永远无法勾勒出一幅更清晰更精确的结构体内存布局图?哦,当然不是。不过先让我们从这个问题中暂时抽身,关注一下另一个重要问题————内存对齐。
许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k( 通常它为4 或8) 的倍数,这就是所谓的内存对齐,而这个k 则被称为该数据类型的对齐模数(alignment modulus) 。当一种类型S 的对齐模数与另一种类型T 的对齐模数的比值是大于1 的整数,我们就称类型S 的对齐要求比T 强( 严格) ,而称T 比S 弱( 宽松) 。这种强制的要求一来简化了处理器与内存之间传输系统的设计,二来可以提升读取数据的速度。比如这么一种处理器,它每次读写内存的时候都从某个8 倍数的地址开始,一次读出或写入8 个字节的数据,假如软件能保证double 类型的数据都从8 倍数地址开始,那么读或写一个double 类型数据就只需要一次内存操作。否则,我们就可能需要两次内存操作才能完成这个动作,因为数据或许恰好横跨在两个符合对齐要求的8 字节内存块上。某些处理器在数据不满足对齐要求的情况下可能会出错,但是Intel 的IA32 架构的处理器则不管数据是否对齐都能正确工作。不过Intel 奉劝大家,如果想提升性能,那么所有的程序数据都应该尽可能地对齐。Win32 平台下的微软C 编译器(cl.exe for 80x86) 在默认情况下采用如下的对齐规则: 任何基本数据类型T 的对齐模数就是T 的大小,即s
相关文档:
这篇文章是使用SQLite C/C++接口的一个概要介绍和入门指南。
由于早期的SQLite只支持5个C/C++接口,因而非常容易学习和使用,但是随着SQLite功能的增强,新的C/C++接口不断的增加进来,到现在有超过150个不同的API接口。这往往使初学者望而却步。幸运的是,大多数SQLite中的C/C++接口是专用的,因而很少被使用到。尽管有这 ......
Delphi 与 C/C++ 数据类型对照表
Delphi数据类型C/C++
ShorInt
8位有符号整数
char
Byte
8位无符号整数
BYTE,unsigned short
SmallInt
16位有符号整数
short
Word
16位无符号整数
unsigned short
Integer,LongInt
32位有符号整数
int,long
Cardinal,LongWord/DWORD
32位无符号整数
unsigned long
Int6 ......
函数调用栈的实现。可用于实现简单的脚本解释器。
声明:
#pragma once
const int BUFFERSIZE = 1024;
const int growfactor = 2;
// this stack is used as call stack.
class TStack{
private:
size_t size; // the stack length
size_t pos; // the stack top position
cha ......
1、在cpp文件中调用c文件中实现的函数的时候,需要用extern "C"声明该函数,否则cpp会按名字改编后的
函数名去找该函数而找不到。
cpp文件调用c文件中函数如下:
c文件中有一函数:
void Transfer(int a; char b);
&nbs ......