首页 > 编程语言 >软件工程师,不了解64位程序开发你就out了

软件工程师,不了解64位程序开发你就out了

时间:2024-09-22 11:52:56浏览次数:3  
标签:示例 32 程序开发 程序 value 64 out size

概述

□ 64位Windows系统下也能运行32位程序,是因为有一个WOW64子系统。它能将32位应用程序的API调用转换成对原生64位系统的调用。正是因为WOW64的存在,32位应用程序在64位系统下并不能发挥最佳的性能,反而比在32位系统下有大约2%的性能损失。如果开发的是64位应用程序,则不需要依赖WOW64运行,并可带来大约5%-15%的性能提升(5%-10%由于采用了64位架构,1%-5%由于未使用WOW64)。


□ 32位程序的最大地址空间是4GB,64位程序的最大地址空间是可以大于4GB的。


□ 64位程序不再区分cdecl、stdcall等各种调用方式。gcc在64位下面,不再支持__attribute((cdecl))__和__attribute((stdcall))__。


□ 64位程序不再使用ESP,而是使用增加的几个64位寄存器,因为ESP不支持64位空间的栈。


□ 虽然在64位Windows系统下可以运行64位和32位进程,但是64位代码和32位代码不能在相同进程上运行。你的代码要么全部是64位,要么全部是32位,要加载的库和组件也要满足这一要求。


数据类型字节长度

32位程序和64位程序,其数据类型的字节长度并不完全一致,可参看下表。

数据类型

32位系统

64位系统

char/bool

1

1

short

2

2

int

4

4

long int

4

Windows:4,Linux:8

long long int

8

8

size_t

4

8

pointer/handle

4

8

float

4

4

double

8

8

time_t

8(VC2005之前:4)

8

ptrdiff_t

4

8


注意事项1

□ 使用“_WIN32”宏(不要用“WIN32”宏)来判断是不是Windows平台编译环境,使用“_WIN64”宏来区分编译环境是32位还是64位。

常量/宏定义

预定义选项

Windows.h

VC编译器

WIN32

支持

支持(在minwindef.h中定义)

不支持

_WIN32

不支持

不支持

支持

_WIN64

不支持

不支持

仅64位支持


注意事项2

□ 64位整型数据在Windows和Linux中的输出格式不一样。

Windows下,可参考下面的示例代码。

__int64 a;
printf("%I64d", a);
unsigned __int64 b;
printf("%I64u", b);
printf("%Iu", c);

Linux下,可参考下面的示例代码。

long long a;
printf("%lld",a);
unsigned long long b;
printf("%llu", b);
size_t c;
printf("%zu", c);


注意事项3

□ 谨慎使用printf、scanf等类似函数。

1、64位程序时,size_t与%u不匹配。下面的代码是不合理的。

const char *invalidFormat = "%u";
size_t value = SIZE_MAX;
printf(invalidFormat, value);

2、64位程序时,指针为8个字节,转化为字符串需要16个字节,内存会溢出。下面的代码是不合理的。

char buf[9];
const char *pointer = "hello";
sprintf(buf, "%p", pointer);


注意事项4

□ 避免使用类似下面的魔法数字,尽量使用sizeof,或者<limits.h>、<inttypes.h>中定义的值。

魔法数字

使用场景

4

某个数据类型的字节数

32

某个数据类型的位数

0x7fffffff

4

0x80000000

4

0xffffffff

8

以下为一些错误使用魔法数字的示例。

size_t ArraySize = N * 4;
intptr_t *Array = (intptr_t *)malloc(ArraySize);

size_t values[ARRAY_SIZE];
memset(values, 0, ARRAY_SIZE * 4);

size_t n, r;
n = n >> (32 - r);

hFileMapping = CreateFileMapping((HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE,  
    (DWORD) 0, (DWORD)(szBufIm), (LPCTSTR)&FileShareNameMap[0]);

正确的示例可参看下面的代码。

size_t ArraySize = N * sizeof(intptr_t);
intptr_t *Array = (intptr_t *)malloc(ArraySize);

size_t values[ARRAY_SIZE];
memset(values, 0, ARRAY_SIZE * sizeof(size_t));
// 或者
memset(values, 0, sizeof(values));

size_t n, r;
n = n >> (CHAR_BIT * sizeof(n) - r); 

hFileMapping = CreateFileMapping((HANDLE)(LONG_PTR)-1, NULL, PAGE_READWRITE,  
    (DWORD) 0, (DWORD)(szBufIm), (LPCTSTR)&FileShareNameMap[0]);

另外,可以通过下面的代码很清楚地看到,-1与魔法数字0xFFFFFFFF在64位程序下的输出值不一样。

#include <iostream>
using namespace std;

void foo(void *ptr)
{
    cout << ptr << endl;
}

int main()
{
    cout << "-1\t\t";
    foo((void *)-1);

    cout << "0xFFFFFFFF\t";
    foo((void *)0xFFFFFFFF);
    
    return 0;
}

32位程序时的输出如下。

-1              FFFFFFFF
0xFFFFFFFF      FFFFFFFF

64位程序时的输出如下。

-1              FFFFFFFFFFFFFFFF
0xFFFFFFFF      00000000FFFFFFFF


注意事项5

□ 不要在整型和指针/句柄间进行转换。如果确实需要转换,请使用intptr_t或uintptr_t。intptr_t和uintptr_t是为了跨平台,其长度总是所在平台的位数,所以用来存放地址。

以下为一些错误的示例。

char *p;
p = (char *) ((int)p & PAGEOFFSET);

DWORD tmp = (DWORD)malloc(ArraySize);
int *ptr = (int *)tmp;

正确的示例可参看下面的代码。

char *p;
p = (char *) ((intptr_t)p & PAGEOFFSET);

DWORD_PTR tmp = (DWORD_PTR)malloc(ArraySize);
int *ptr = (int *)tmp;


注意事项6

□ 为了保证通用性,在进行数据交换时,尽量不要使用long、size_t等会随平台变化的类型,最好使用固定大小的数据类型。

以下为一些错误的示例。

size_t PixelsCount;
fread(&PixelsCount, sizeof(PixelsCount), 1, inFile);
              
__int32 value_1;
SSIZE_T value_2;
inputStream >> value_1 >> value_2;

正确的示例可参看下面的代码。

size_t PixelsCount;
__uint32 tmp;
fread(&tmp, sizeof(tmp), 1, inFile);
PixelsCount = static_cast<size_t>(tmp);

__int32 value_1;
__int32 value_2;
inputStream >> value_1 >> value_2;


注意事项7

□ 尽量不要在不兼容的类型上进行指针的转换。

我们来看看下面的示例。

#include <iostream>
using namespace std;

int main()
{
    int array[4] = { 1, 2, 3, 4 };
    size_t *sizetPtr = (size_t *)(array);
    cout << sizetPtr[1] << endl;
    return 0;
}

在上面的示例中,32位程序会输出:1,64位程序会输出:17179869187。这是因为,64位程序时,size_t为8个字节,指针转换后,sizetPtr的第二个元素的值为:0x0000000400000003。

软件工程师,不了解64位程序开发你就out了_Windows


注意事项8

□ 在联合体中谨慎使用指针。

我们来看看下面的示例。

union PtrNumUnion
{
    char *m_p;
    unsigned m_n;
} u;

u.m_p = str;
u.m_n += delta;

这段示例代码在32位程序时,运行正常。但在64位程序时,可能会导致运行异常甚至崩溃。在64位程序下,指针m_p为8个字节,m_n为4个字节,并不完全对应;如果用m_n作为指针来使用,会导致指针的值不正确。

软件工程师,不了解64位程序开发你就out了_64位程序_02


注意事项9

□ 在进行移位操作时,要避免溢出。

我们来看看下面的示例。

ptrdiff_t SetBitN(ptrdiff_t value, unsigned bitNum)
{
     ptrdiff_t mask = 1 << bitNum;
     return value | mask;
}

32位程序时,bitNum从0到31时,移位后mask的值均正常。

64位程序时,bitNum取值范围一般为0到63;但当取值为32到63时,mask的值都是不正确的。

为什么会这样呢?因为常量数字1默认为int类型,当位移的位数大于等于32时,会发生溢出。溢出后,mask的值可能是1,也可能是0,具体要看编译器的实现。

正确的方法是:先把常量数字转换为需要的类型,再进行移位。可参考下面的代码。

ptrdiff_t SetBitN(ptrdiff_t value, unsigned bitNum)
{
     ptrdiff_t mask = ptrdiff_t(1) << bitNum;
     return value | mask;
}


标签:示例,32,程序开发,程序,value,64,out,size
From: https://blog.51cto.com/u_16794707/12079935

相关文章

  • ORA-01558: out of transaction ID’s in rollback segment SYSTEM
    联系:手机/微信(+8617813235971)QQ(107644445)标题:ORA-01092ORA-00604ORA-01558故障处理作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任的权利.]客户一个11.2.0.1的库,在重启之前报ORA-00604和ORA-01558:outoftransactionID’sinrol......
  • 如何使用 React Router DOM
    介绍欢迎来到我们关于reactrouterdom的深入教程!如果您是一名ui开发人员,希望通过动态路由功能增强react应用程序,那么您来对地方了。reactrouterdom是一个功能强大的库,允许您创建具有多个视图的单页面应用程序,同时保持流畅、无缝的用户体验。在这份综合指南中,我们将引导......
  • 幼儿园管理系统 毕业设计-附源码86464
    目 录1绪论1.1研究背景与意义1.2国内外研究现状1.3论文结构与章节安排2 系统分析2.1可行性分析2.1.1技术可行性分析2.1.2 经济可行性分析2.1.3法律可行性分析2.2系统功能分析2.2.1功能性分析2.2.2非功能性分析2.3 系统用例分析2.4......
  • 使用 React Router v6 进行布局
    第1步:设置reactrouterv6npmi-dreact-router-dom@latest登录后复制第2步:定义路由结构接下来,在app.js文件中定义路由的结构。我们将为主页、关于页面和联系页面创建路由,并将它们与相应的组件关联起来。//app.jsimportreactfrom'react';import{browserroutera......
  • 自制CANTool_DBC_Layout仿制_基本框架练习(一)
    1、工具制作用途    模仿DBC中对于Layout方案的模仿,先完成一些基本功能,数据导入和信号解析2、工具UI1、初始化CAN的布局2、导入CANMessage信号3、导入CANSignal1、初始化CANFD的布局2、导入CANFDMessage信号3、导入CANFDSignal3、工具代码#reg......
  • TikTok提示“Network is out of reach”怎么处理?
    当TikTok提示“Networkisoutofreach”时,意味着应用无法连接到互联网。导致这一问题的常见原因包括网络连接不稳定、地理限制或网络设置与应用不兼容等。解决方法有:拔除手机卡、关闭手机定位服务、切换至稳定的海外IP网络等。使用TikTok专用网络也可以帮助解决连接问题,从而......
  • AI论文写作PPT思维导图PC小程序开发
    AI论文写作PPT思维导图PC小程序开发AI智能PPT功能一键生成PPT大纲、一键扩写大纲内容、单独扩写某个大纲内容、一键生成内容关键词、单项内容关键词生成、新增大纲项、修改大纲、删除大纲、选择PPT模板、单页模板一键切换、在线编辑模板;支持导出PPTX、JPEG、;PNG、JSON、PDF格式文件......
  • 丧尸围城bink2w64.dll文件丢失?专家级修复丧尸围城因bink2w64.dll缺失导致的启动错误
    针对《丧尸围城》游戏中因bink2w64.dll文件丢失导致的启动错误,我们可以采取一系列专家级的修复方法。以下是一些详细步骤和建议:一、确认问题首先,确认游戏启动错误确实是由于bink2w64.dll文件丢失所致。这通常会在游戏启动时出现错误提示,明确指出该文件缺失。二、重新安装游......
  • Vue-router路由
    目录16.1介绍16.2vue的路由16.3安装路由模块16.5声明式路由16.5.1创建MyInfo.vue16.5.1创建Admin.vue16.5.2创建静态路由表16.5.3main.js引入路由模块并使用16.5.4App.vue使用路由16.6编程式路由16.7参数的传递16.7.1声明式路由传参16.7.2编程式路由......
  • Vue 前端 504 代理错误(Gateway timeout)
    当在Vue前端应用中遇到504代理错误时,这通常意味着请求在到达服务器之前超时了。504错误代码表示网关超时,即代理服务器没有在规定时间内从上游服务器收到响应。这种情况可能由多种原因引起,以下是一些常见的原因及解决方法:常见原因及解决方法后端服务响应慢或未响应检查后端服务......