从 const char* 参数中取出索引

Posted

技术标签:

【中文标题】从 const char* 参数中取出索引【英文标题】:Taking an index out of const char* argument 【发布时间】:2017-01-24 10:42:10 【问题描述】:

我有以下代码:

int some_array[256] =  ... ;

int do_stuff(const char* str)

   int index = *str;
   return some_array[index];

显然,上面的代码在某些平台上会导致错误,因为 *str 实际上可以为负数。

于是我想到了两种可能的解决方案:

    将值转换为赋值 (unsigned int index = (unsigned char)*str;)。

    改为传递const unsigned char*

编辑:这个问题的其余部分没有得到处理,所以我把它移到了一个新线程。

【问题讨论】:

为什么将索引作为字符串传递?你想达到什么目的? 真的吗?为什么要将char * 传递给函数,并将其指向的内容用作静态数组的索引? ".. *str 实际上可以是负数" 不应该是一个错误。如果调用代码没有正确处理它,那么bug就在那里,不在这个sn-p中。 @Raw N - 即使是稍微不错的技术也会有所改进。 @qrdl:字符串操作的查找表是一种非常重要的实现技术。 【参考方案1】:

char 的签名确实与平台有关,但您知道char 的值与unsigned char 的值一样多,并且转换是单射的。因此,您绝对可以将值转换为将查找索引与每个字符相关联:

unsigned char idx = *str;
return arr[idx];

您当然应该确保arr 至少有UCHAR_MAX + 1 元素。 (当sizeof(unsigned long long int) == 1 时,这可能会导致热闹的边缘情况,幸运的是这种情况很少见。)

【讨论】:

其实协议使用八位字节,所以只需要保证数组有256个元素即可。 UCHAR_MAX>255 是否无关紧要,因为任何可能的输入都不能包含这样的值。 @MSalters:是的,我要说的是——如果你有关于预期输入的信息,你可以将查找表限制为那个(并断言)。【参考方案2】:

字符可以有符号或无符号,具体取决于平台。无符号范围的假设是导致您的错误的原因。

您的do_stuff 代码不会将const char* 视为字符串表示形式。它将它用作查找表中的字节大小的索引序列。因此,在do_stuff 内的字符串字符上强制输入unsigned char 并没有错(即使用您的解决方案#1)。这使char 的重新解释为本地化到do_stuff 函数实现的索引。

当然,这假设您的代码的其他部分确实将 str 视为 C 字符串。

【讨论】:

以上是关于从 const char* 参数中取出索引的主要内容,如果未能解决你的问题,请参考以下文章

求助:error C2664: “CreateWindowExW”: 不能将参数 3 从“const char [8]”转换为“LPCWSTR”

error C2664: “StrCmpW”: 不能将参数 2 从“const char [12]”转换为“PCWSTR”

const char* const* p 参数在 g++ 中编译但不是 gcc

用常量参数定义 main (const int argc, const char * const argv[])?

error C2664: “int CWnd::MessageBoxW(LPCTSTR,LPCTSTR,UINT)”: 无法将参数 1 从“const char [9]”转换为“LPCTSTR”

如何在函数中使用 strcmp() 时修复预期的“const char *”但参数的类型为“char **”