我正在用 C 创建一个哈希表的实现,用于教育目的。
哈希函数应返回 size_t 哈希值。由于size_t的大小在不同的平台上是不同的(并且我想使用散列函数来对size_t中的所有位进行散列),所以我想到为不同的大小创建不同的散列函数。由于哈希函数将用作函数指针,我怀疑编译器无法像这样内联代码:
size_t hash4(void* key, size_t size);
size_t hash8(void* key, size_t size);
size_t hash(void* key, size_t size)
{
if (sizeof(size_t) == 4)
{
return hash4(key, size);
}
else if (sizeof(size_t) == 8)
{
return hash8(ket, size);
}
}
size_t (*hashFunc)(void* key, size_t size) = hash;
Run Code Online (Sandbox Code Playgroud)
每次调用哈希函数时都会使用两级间接。
这就是为什么我想到做这样的事情:size_t (*hashFunc)(void* key, size_t size) = hash##sizeof(size_t);相反。将仅使用一级间接。问题是 sizeof 运算符在前置阶段不可用。
那么定义一个预处理器值的好方法是什么,该值将在每个平台上扩展为正确的 size_t 大小?我想我可以检查预定义的宏,但我想知道是否有更好的方法。
所以我知道C Compatability Headers中的任何标题:
在全局命名空间中放置相应的cxxx头将放置在
std命名空间中的每个名称
我也知道这些C头文件在c ++ 17中已被弃用,赞成它们的兼容性"cxxx"对应物.
现在,我相信它size_t仅由标准定义标题定义.所以我认为这在技术上意味着size_t全局命名空间中的定义已被弃用?
我已经使用它多年了,size_t而且在转向使用之前我只是想确认一下std::size_t.
%zuC 中的字符串格式化和之间有什么区别%lu?%lu用于unsigned long值并%zu用于size_t值,但实际上,size_t只是一个unsigned long. CppCheck 对此有所抱怨,但根据我的经验,这两种类型都适用。
只是%zu一种标准化的格式化方式,size_t因为size_t很常用,还是还有更多内容?
GCC 4.4.1,C99
我正在使用size_t,而且size_t是一个unsigned int.但是,这取决于您是运行32位还是64位.
我将size_t用于存储缓冲区的大小.
因此,如果跨架构使用,我认为这不会是非常便携的.
只是一个问题,使用size_t32位或64位.什么情况会导致最严重的问题?
我有代码:
unsigned int length = strlen(somestring);
Run Code Online (Sandbox Code Playgroud)
我与4警告级别编译和它告诉我,"转换,从size_t到unsigned int,可能的数据丢失",当size_t是typedef一个unsigned int.
为什么!?
编辑:
我刚解决了自己的问题.我是XP用户,我的编译器正在检查64位兼容性.由于size_t是平台相关的,对于64位,它将是一个unsigned long long,其中它与a不同unsigned int.
我定义了一个函数:
void myfunc(size_t param1, size_t param2){
...
}
Run Code Online (Sandbox Code Playgroud)
它工作正常.但是当我尝试重载此功能时
void myfunc(unsigned long param1, unsigned long param2){
...
}
Run Code Online (Sandbox Code Playgroud)
它无法使用以下消息进行编译:错误:myfunc(unsigned long param1,unsigned long param2)无法重载.
如果没有staic_cast输入参数size_t,我该如何解决这个问题?
谢谢!
我有困难之间的选择size_t和ptrdiff_t对性的指标,应该需要能够存储负值的类型.
确切地说,在我的代码中,我需要实现一个数组.我收到它的长度(在构造函数中)作为一种类型size_t,当我重载时[] operator我需要索引是类型ptrdiff_t(而不是size_t),因为我想允许负索引,如下例所示:
std::size_t length = 50;
MyVector<int> vec(length);
vec[0] = 10;
MyVector<int> vec2 = vec+1;
std::cout << vec2[-1] << std::endl; //should print 10
Run Code Online (Sandbox Code Playgroud)
所述设计产生的问题是可用指数的范围受到最大值的限制ptrdiff_t,并且在一些机器中,该上限小于最大值size_t.
即 std::numeric_limits<std::ptrdiff_t>::max() < std::numeric_limits<std::size_t>::max()
因此,问题是用户可能会创建一个大小超过最大值ptrdiff_t(size_t当然仍在其范围内)的数组ptrdiff_t,但是他无法访问数组的元素,而这些元素的成功超过了最大值,因为它们的索引会溢出到负数.在我的机器上,这将可用的索引减少了一半!(因为这两个size_t和ptrdiff_t是64位,但一个是unsigned,另一个是signed)
以下是我提出的解决方案,但遗憾的是它们都不是完美的:
在构造函数中,接受一个类型的长度ptrdiff_t而不是size_t,并添加一个检查,以验证给定的长度不是负的.
优点:它解决了这个问题,因为现在我可以访问数组中的所有元素,并且仍然允许负索引.
缺点:它限制了数组的最大可能长度.(就像我之前说过的那样,在我的机器中减少了一半)
保持原样,但在其中[] operator,将索引转换为类型size_t,并利用负值溢出的事实. …
首先,我的意思是'正确定义'?
例如,"C编程语言"第2版中的 K&R .,在2.2数据类型和大小中,对整数做出非常明确的陈述:
- 还有
short,int与long用于整数类型.他们需要重复不同边界的价值观.int是特定硬件的"自然"大小的数字,因此也可能是最快的.- 尺寸为整数类型
short,int而long纯粹是实现相关的.- 但他们有限制.
short并且int应至少保留16位.long应至少保留32位.short> =int> =long.
这是非常明确和明确的.size_t类型不是这种情况.在K&R 5.4地址算术中,他们说:
- ...
size_t是sizeof运算符返回的无符号整数类型.- 的
sizeof操作者产生存储其操作数的类型的对象所需要的字节数.
在C99标准草案中,在6.5.3.4尺寸操作员中,他们说:
- 结果的值是实现定义的,其类型(无符号整数类型)
size_t在<stddef.h>(和其他头文件)中定义.
在7.17通用定义中:
size_t这是sizeof运算符的结果的无符号整数类型;
在7.18.3其他整数类型的限制中:
- size_t
SIZE_MAX65535的限制
还有一篇有用的文章 - 为什么size_t很重要.它说如下:
- 好吧,让我们试着想象一下,如果没有,会是什么样的
size_t.- 例如,让我们从中获取 …
下面这个问题,我决定使用std::size_t作为size_type每一个容器,明显可读性的原因.我知道理论上可能std::container<T>::size_type不是std::size_t,但我认为现在和未来的配置并非如此.
但是,为了避免邪恶的错误,我在使用时检查类型是否相同.例如:
BOOST_STATIC_ASSERT(boost::is_same< std::vector<double>::size_type , std::size_t >::value);
std::vector<double> x;
/* fill x */
for(std::size_t i = 0; i < x.size(); ++i) { /* do something */ }
Run Code Online (Sandbox Code Playgroud)
在代码中的另一个地方,我用了一个std::vector<long int>,然后我也检查:
BOOST_STATIC_ASSERT(boost::is_same< std::vector<long int>::size_type , std::size_t >::value);
Run Code Online (Sandbox Code Playgroud)
然后,哦不!我用std::vector<std::list<std::string>*>和std::vector<std::list<double*>*>,然后我检查:
BOOST_STATIC_ASSERT(boost::is_same< std::vector<std::list<std::string>*>::size_type , std::size_t >::value);
BOOST_STATIC_ASSERT(boost::is_same< std::vector<std::list<double*>*>::size_type , std::size_t >::value);
Run Code Online (Sandbox Code Playgroud)
好的,我想你明白了这个问题.线条难看,难以维护代码.这是个坏主意.
然后,我的问题是:如果我检查std::vector<any_common_type>::size_type是std::size_t,是否有任何机会std::vector<another_type>::size_type不是std::size_t?只检查分离文件中的一些常见类型以确保std::container::size_type始终std::size_t在我的编译器上是否足够?
注意:出于兼容性原因,我不使用C++ 11.
我正在使用下面的简单交换排序算法在Windows中的Visual Studio项目中尝试不同的整数类型.处理器是英特尔.代码是在Release x64中编译的.优化设置为"最大化速度(/ O2)".与编译设置对应的命令行是
/permissive- /GS /GL /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /sdl /Fd"x64\Release\vc141.pdb" /Zc:inline /fp:precise /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Gd /Oi /MD /Fa"x64\Release\" /EHsc /nologo /Fo"x64\Release\" /Fp"x64\Release\SpeedTestForIntegerTypes.pch" /diagnostics:classic
Run Code Online (Sandbox Code Playgroud)
代码本身:
#include <ctime>
#include <vector>
#include <iostream>
void sort(int N, int A[], int WorkArray[]) // exchange sort
{
int i, j, index, val_min;
for (j = 0; j < N; j++)
{
val_min = 500000;
for (i = j; i < N; i++) …Run Code Online (Sandbox Code Playgroud) size-t ×10
c++ ×6
c ×4
32bit-64bit ×1
arrays ×1
c++03 ×1
c11 ×1
c99 ×1
hash ×1
hashtable ×1
indexing ×1
int ×1
long-integer ×1
namespaces ×1
performance ×1
portability ×1
printf ×1
ptrdiff-t ×1
size-type ×1
stl ×1
types ×1
unsigned ×1