特定于c ++的问题。所以我读了一个关于什么使程序32位/ 64位的问题,它得到的anwser是这样的(对不起,我无法找到问题,是有一天前我看着它,我再也找不到它了:():只要你不做任何“指针假设”,你只需要重新编译它。所以我的问题是,什么是指针假设?据我所知有32位指针和64位指针所以我认为这是与请在它们之间显示代码之间的差异。编写代码时要记住的任何其他好习惯,这有助于它使得它之间易于转换也欢迎:)请与他们分享示例
聚苯乙烯。我知道有这篇文章: How do you write code that is both 32 bit and 64 bit compatible? 但对于像我这样的新程序员来说,对于没有好例子的人来说,这很有道理。像什么是32位存储单元等。有点跳跃,以打破它更多(没有双关语意图^^)ds。
答案 0 :(得分:6)
一般来说,这意味着你的程序行为永远不应该依赖于任何类型的sizeof()
(不是一些确切的大小),既不明确也不隐含(这也包括可能的结构对齐)
指针只是它们的一个子集,它可能也意味着你不应该试图依赖能够在不相关的指针类型和/或整数之间进行转换,除非它们是专门为此做的(例如{{1} })。
以同样的方式你需要处理写入磁盘的东西,你也应该从不依赖于例如磁盘的大小。内置类型,无处不在。
每当必须(因为例如外部数据格式)时,请使用明确大小的类型,例如intptr_t
。
答案 1 :(得分:3)
“指针假设”是指您编写的代码依赖于适合其他数据类型的指针,例如: int copy_of_pointer = ptr;
- 如果int是32位类型,则此代码将在64位计算机上中断,因为只存储部分指针。
只要指针只存储在指针类型中,它就应该没问题了。
通常,指针是“机器字”的大小,因此在32位架构上,32位,在64位架构上,所有指针都是64位。但是,有些架构并不是这样。我自己从来没有在这样的机器上工作[除了x86以及它的“远”和“近”指针 - 但现在让我们忽略它。)
大多数编译器会告诉你何时将指针转换为指针不适合的整数,所以如果启用警告,问题的大部分将变得明显 - 修复警告,并且你的代码将很可能是相当不错的马上工作。
答案 2 :(得分:3)
对于格式良好的程序(即根据C ++的语法和语义规则编写而没有未定义行为的程序),C ++标准保证您的程序将具有一组可观察行为。可观察行为因程序中未指定的行为(包括实现定义的行为)而异。如果您避免未指定的行为或解决它,您的程序将保证具有特定和特定的输出。如果以这种方式编写程序,您将看到32位或64位计算机上的程序没有差异。
具有不同可能输出的程序的简单(强制)示例如下:
int main()
{
std::cout << sizeof(void*) << std::endl;
return 0;
}
该程序可能在32位和64位计算机上具有不同的输出(但不一定)。 sizeof(void*)
的结果是实现定义的。但是,当然可以有一个程序包含实现定义的行为,但解决方案是明确定义的:
int main()
{
int size = sizeof(void*);
if (size != 4) {
size = 4;
}
std::cout << size << std::endl;
return 0;
}
该程序将始终打印出4
,尽管它使用实现定义的行为。这是一个愚蠢的例子,因为我们刚刚完成了int size = 4;
,但有些情况下会出现在编写与平台无关的代码中。
因此编写可移植代码的规则是:旨在避免或解决未指定的行为。
以下是避免未指明行为的一些提示:
除了C ++标准指定的基本类型之外,不要假设任何基本类型的大小。也就是说,char
至少为8位,short
和int
都至少为16位,依此类推。
不要尝试做指针魔术(在指针类型之间转换或在整数类型中存储指针)。
不要使用unsigned char*
来读取非char
对象的值表示(用于序列化或相关任务)。
避免使用reinterpret_cast
。
执行可能上溢或下溢的操作时要小心。在进行位移操作时要仔细考虑。
对指针类型进行算术时要小心。
请勿使用void*
。
标准中出现了更多未指定或未定义的行为。非常值得一试。在线some great articles涵盖了您在32位和64位平台之间遇到的一些常见差异。
答案 3 :(得分:1)
32位代码和64位代码之间没有区别,C / C ++和其他编程语言的目标是它们的可移植性,而不是汇编语言。
唯一的区别是您将编译代码的发行版,所有工作都由编译器/链接器自动完成,所以不要考虑这一点。
但是:如果您使用64位分布式编程,并且需要使用外部库(例如SDL),那么如果您希望编译代码,外部库也必须以64位编译。
要知道的是,你的ELF文件在64位分布上比在32位分区上更大,这只是逻辑。
指针有什么意义?当您递增/更改指针时,编译器将指针从指向类型的大小递增。
包含的类型大小由处理器的寄存器大小/您正在处理的发行版定义。
但是你不必关心这个,编译会为你做一切。
总结:这就是为什么你不能在32位发行版上执行64位ELF文件。
答案 4 :(得分:1)
32位/ 64位移植的典型缺陷是:
程序员隐含的假设sizeof(void *)== 4 * sizeof(char)。 如果你正在做这个假设,例如以这种方式分配数组(&#34;我需要20个指针,所以我分配80个字节&#34;),你的代码在64位上中断,因为它会导致缓冲区溢出。
小猫杀手&#34; ,int x =(int)&amp; something; (反之,void * ptr =(void *)some_int)。同样假设sizeof(int)== sizeof(void *)。这不会导致溢出但会丢失数据 - 指针的高32位,即。
这两个问题都属于一个称为类型别名的类(假设在两种类型之间的二进制表示级别上具有同一性/可互换性/等价性),并且这种假设很常见;比如在UN * X上,假设time_t,size_t,off_t为int,或者在Windows上,HANDLE,void *和long可以互换等等......
关于数据结构/堆栈空间使用的假设(参见下面的5.)。在C / C ++代码中,局部变量在堆栈上分配,由于下面的要点,在32位和64位模式之间使用的空间不同,并且由于传递参数的规则不同(32位x86通常在堆栈上,64位x86部分在寄存器中)。在32位上使用默认堆栈大小的代码可能会导致64位堆栈溢出崩溃。 这很容易被发现是导致崩溃的原因,但取决于可能难以修复的应用程序的可配置性。
32位和64位代码之间的时序差异(由于不同的代码大小/缓存占用空间,或不同的内存访问特征/模式,或不同的调用约定)可能会破坏&#34;校准&#34;。比如说,对于(int i = 0; i&lt; 1000000; ++ i)sleep(0);对于32位和64位可能会有不同的时间......
最后,ABI(应用程序二进制接口)。 64位和32位环境之间通常比指针大小差异更大...... 目前,有两个主要的分支机构&#34;存在64位环境,IL32P64(Win64使用什么 - int和long是int32_t,只有uintptr_t / void *是uint64_t,根据大小整数来说)和LP64(UN * X使用的是 - int是int32_t,long是int64_t和uintptr_t / void *是uint64_t),但是有&#34;细分&#34;不同的对齐规则也是如此 - 某些环境假定它们各自大小的长,浮点或双对齐,而其他环境则假设它们以四个字节的倍数对齐。在32位Linux中,它们全部以四个字节对齐,而在64位Linux中,浮点数以四字节长,双字节对齐八字节倍数。 这些规则的结果是,在许多情况下,即使数据类型声明完全相同,bith sizeof(struct {...})和结构/类成员的偏移量在32位和64位环境之间也是不同的。 除了影响阵列/矢量分配之外,这些问题还影响数据输入/输出,例如通过文件 - 如果32位应用程序写入,例如struct {char a; int b; char c,long d;对于同一个应用程序为64位重新编译的文件读取时,结果将不是所希望的。 刚刚给出的示例仅涉及语言原语(char,int,long等),但当然会影响各种依赖于平台的/运行时库数据类型,无论是size_t,off_t,time_t,HANDLE,基本上是任何非平凡的struct / union / class ... - 所以这里的错误空间很大,
然后出现了较低级别的差异,例如:用于手动优化组装(SSE / SSE2 / ...); 32位和64位具有不同(数量)的寄存器,不同的参数传递规则;所有这些都强烈地影响了这种优化的执行方式,并且很可能是这样的。在32位模式下提供最佳性能的SSE2代码需要重写/需要增强才能提供最佳性能的64位模式。
还有代码设计约束,对于32位和64位非常不同,特别是在内存分配/管理方面;一个经过精心编码的应用程序,可以最大限度地利用存储器中的内存,它可以在32位&#34;将有关于如何/何时分配/释放内存,内存映射文件使用,内部缓存等的复杂逻辑 - 其中大部分将在64位中是有害的,你可以简单地#34;利用巨大的可用地址空间。这样的应用程序可能会重新编译64位就好了,但是执行起来比一些&#34;古老的简单弃用版本更糟糕&#34;它没有所有最大化的32位窥视孔优化。
所以,最终,它也是关于增强/增益的,而且更多的工作,部分是编程,部分是设计/需求的工作。即使你的应用程序干净地重新编译32位和64位环境并在两者上都经过验证,它真的受益于64位吗?是否可以/应该对代码逻辑进行更改以使其在64位中更快/更快地运行?你能否在不破坏32位向后兼容性的情况下进行这些更改没有对32位目标的负面影响?增强功能将在哪里,您可以获得多少? 对于大型商业项目,这些问题的答案通常是路线图上的重要标记,因为您的出发点是一些现有的&#34;赚钱机器&#34; ...