以前使用Delphi
调用海康SDK时,专门改写过HCNetSDK.h
,当时大部分桌面应用还都是32位的,毕竟64位还没彻底普及开(即便现在,还是有一部分桌面考虑兼容性依然是32位)。后来也搞过64位版的,编译没问题,运行就不成功。虽然没成功,但心里还是清楚这基本上是数据类型
的问题,由于对64位了解不多,也就一直搁置着。
转Lazarus
之后,又搞过一次64位版,还是没成功。后来知道有ctypes
这个单元,也知道这是专门针对c语言
数据类型的,但一直没去看过。近来又想起这个事,就想一探究竟。
直接看源码,其实就是给pascal
的数据类型取了个c
的别名。要想了解透彻,自已撸码跑一下还是很有必要的:
program test;
uses
SysUtils,
ctypes;
begin
writeln(Format('%-16s%s', ['type', 'size']));
writeln('--------------------');
writeln(Format('%-16s%d', ['cint8', SizeOf(cint8)]));
writeln(Format('%-16s%d', ['cuint8', SizeOf(cuint8)]));
writeln(Format('%-16s%d', ['cchar', SizeOf(cchar)]));
writeln(Format('%-16s%d', ['cschar', SizeOf(cschar)]));
writeln(Format('%-16s%d', ['cuchar', SizeOf(cuchar)]));
writeln(Format('%-16s%d', ['cint16', SizeOf(cint16)]));
writeln(Format('%-16s%d', ['cuint16', SizeOf(cuint16)]));
writeln(Format('%-16s%d', ['cshort', SizeOf(cshort)]));
writeln(Format('%-16s%d', ['csshort', SizeOf(csshort)]));
writeln(Format('%-16s%d', ['cushort', SizeOf(cushort)]));
writeln(Format('%-16s%d', ['cint32', SizeOf(cint32)]));
writeln(Format('%-16s%d', ['cuint32', SizeOf(cuint32)]));
writeln(Format('%-16s%d', ['cint64', SizeOf(cint64)]));
writeln(Format('%-16s%d', ['cuint64', SizeOf(cuint64)]));
writeln(Format('%-16s%d', ['clonglong', SizeOf(clonglong)]));
writeln(Format('%-16s%d', ['cslonglong', SizeOf(cslonglong)]));
writeln(Format('%-16s%d', ['culonglong', SizeOf(culonglong)]));
writeln(Format('%-16s%d', ['cbool', SizeOf(cbool)]));
writeln(Format('%-16s%d', ['cint', SizeOf(cint)]));
writeln(Format('%-16s%d', ['csint', SizeOf(csint)]));
writeln(Format('%-16s%d', ['cuint', SizeOf(cuint)]));
writeln(Format('%-16s%d', ['clong', SizeOf(clong)]));
writeln(Format('%-16s%d', ['cslong', SizeOf(cslong)]));
writeln(Format('%-16s%d', ['culong', SizeOf(culong)]));
writeln(Format('%-16s%d', ['csigned', SizeOf(csigned)]));
writeln(Format('%-16s%d', ['cunsigned', SizeOf(cunsigned)]));
writeln(Format('%-16s%d', ['csize_t', SizeOf(csize_t)]));
writeln(Format('%-16s%d', ['cfloat', SizeOf(cfloat)]));
writeln(Format('%-16s%d', ['cdouble', SizeOf(cdouble)]));
writeln(Format('%-16s%d', ['clongdouble', SizeOf(clongdouble)]));
Readln();
end.
做为对比,c
的也来一下:
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
int main(int argc, char *argv[]) {
printf("%s\t %d\n","int8_t",sizeof(int8_t));
printf("%s\t %d\n","uint8_t",sizeof(uint8_t));
printf("%s\t %d\n","char",sizeof(char));
printf("%s\t %d\n","signed char",sizeof(signed char));
printf("%s\t %d\n","unsigned char",sizeof(unsigned char));
printf("%s\t %d\n","int16_t",sizeof(int16_t));
printf("%s\t %d\n","uint16_t",sizeof(uint16_t));
printf("%s\t %d\n","short",sizeof(short));
printf("%s\t %d\n","signed short",sizeof(signed short));
printf("%s\t %d\n","unsigned short",sizeof(unsigned short));
printf("%s\t %d\n","int32_t",sizeof(int32_t));
printf("%s\t %d\n","uint32_t",sizeof(uint32_t));
printf("%s\t %d\n","int64_t",sizeof(int64_t));
printf("%s\t %d\n","uint64_t",sizeof(uint64_t));
printf("%s\t %d\n","long long",sizeof(long long));
printf("%s\t %d\n","signed long long",sizeof(signed long long));
printf("%s\t %d\n","unsigned long long",sizeof(unsigned long long));
printf("%s\t %d\n","bool",sizeof(bool));
printf("%s\t %d\n","int",sizeof(int));
printf("%s\t %d\n","signed int",sizeof(signed int));
printf("%s\t %d\n","unsigned int",sizeof(unsigned int));
printf("%s\t %d\n","long",sizeof(long));
printf("%s\t %d\n","signed long",sizeof(signed long));
printf("%s\t %d\n","unsigned long",sizeof(unsigned long));
printf("%s\t %d\n","signed",sizeof(signed));
printf("%s\t %d\n","unsigned",sizeof(unsigned));
printf("%s\t %d\n","size_t",sizeof(size_t));
printf("%s\t %d\n","float",sizeof(float));
printf("%s\t %d\n","double",sizeof(double));
printf("%s\t %d\n","long double",sizeof(long double));
return 0;
}
分别用32位
和64位
编译运行,然后,然后就凌乱了~
// Lazarus | // c
// type 32bit 64bit | // type 32bit 64bit
----------------------- | ------------------------------
cint8 1 1 | int8_t 1 1
cuint8 1 1 | uint8_t 1 1
cchar 1 1 | char 1 1
cschar 1 1 | signed char 1 1
cuchar 1 1 | unsigned char 1 1
cint16 2 2 | int16_t 2 2
cuint16 2 2 | uint16_t 2 2
cshort 2 2 | short 2 2
csshort 2 2 | signed short 2 2
cushort 2 2 | unsigned short 2 2
cint32 4 4 | int32_t 4 4
cuint32 4 4 | uint32_t 4 4
cint64 8 8 | int64_t 8 8
cuint64 8 8 | uint64_t 8 8
clonglong 8 8 | long long 8 8
cslonglong 8 8 | signed long long 8 8
culonglong 8 8 | unsigned long long 8 8
cbool 4 4 | bool 1 1
cint 4 4 | int 4 4
csint 4 4 | signed int 4 4
cuint 4 4 | unsigned int 4 4
clong 4 4 | long 4 4
cslong 4 4 | signed long 4 4
culong 4 4 | unsigned long 4 4
csigned 4 4 | signed 4 4
cunsigned 4 4 | unsigned 4 4
csize_t 4 8 | size_t 4 8
cfloat 4 4 | float 4 4
cdouble 8 8 | double 8 8
clongdouble 12 8 | long double 12 16
cbool
的差异大概知道是怎么回事,这clongdouble
是个什么鬼?难道是bug?
先说cbool
,在win
平台上,使用c
的bool
类型的很少,大多数都是用微软的BOOL
,而32位
平台上的BOOL
确实是4B
,64位
的没研究过,想来为了可移植性应该也是4B
。
再说clongdouble
,从感官上讲,64位
类型比32位
要大才是正常的,而Lazarus
的clongdouble
,64位
比32位
还小,似乎是有问题的。
深深地怀疑这是个bug,然后提了Issues。大概一个小时后,大佬maynard philbrook回复了:
From what I know, and that isn't much. the Fpc 64-bit compiler does not use the Extended float type because it doesn't use the FPU, just the 64-bit registers that exist to performs the double math.
From what I understand it was decided that way because function API calls in the OS do it this way so local support for FPU isn't there.
But is used in the 32-bit target.
Good luck and have a good day.
大意是说:fpc
的64位
编译器不使用扩展浮点类型,因为它不使用FPU
浮点处理单元,只使用用于执行双精度数学运算的64位寄存器,这也是出于考虑到操作系统的API
是这么调用的。但是32位
的编译器还是使用FPU
的。
呃~这一下就扯到编译器上了,完全是咱的知识盲区嘛!既然大佬都这么说了,而且也这么多年了,肯定是不会错的,那么,就当是长了次见识了吧!
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。