为什么这些C / Cython数组被定义为字符数组而不是整数数组?

0 投票
2 回答
1059 浏览
提问于 2025-04-16 02:08

为了回答在StackOverflow上提出的第 #3367795 的问题,我需要解决一些小问题。其中一个问题是:在这个算法(莱文斯坦距离)中,内存中分配了几个数组,并用以下代码进行了初始化。

cdef char   *m1     = <char *>calloc(   blen + 2,    sizeof( char ) )
cdef char   *m2     = <char *>calloc(   blen + 2,    sizeof( char ) )
cdef char   *m3     = <char *>malloc( ( blen + 2 ) * sizeof( char ) )
#.........................................................................
for i from 0 <= i <= blen:
  m2[ i ] = i
  <...snip...>

blen 这里指的是一个Python bytes 变量的长度。根据我对这个算法的理解(完整代码可以查看我的原始帖子),以及初始化 m2 的代码清楚地显示,这些数组是用来存放整数,而不是字符,所以我们可能会认为正确的分配方式应该是这样的:

cdef int    *m3     = <int *>malloc( ( blen + 2 ) * sizeof( int ) )

等等。有没有人能告诉我,为什么这里用到了 char?另外,对于那些对Cython感兴趣的人来说,为什么会有一个 <char *> 的转换?我们本来会认为 char *x = malloc( ... ) 就足够定义 x 了。

2 个回答

8

尽管名字有点误导,但在C语言中,char类型其实是普通的整数类型,就像shortintlong这些一样。在所有整数类型中,char的范围是最小的,占用的内存也最少。所以,如果你的应用程序需要尽量节省内存,使用char而不是int可能会更合适。

在某些硬件平台上,int类型的运算速度可能比char类型快,因此选择具体的类型就变成了速度和内存的权衡。不过,再次强调,在很多情况下,如果char的范围足够用,使用char而不是int可能会更合理。

2

简单来说,使用这种方式是为了节省内存。不过要注意,声明这些数组为 char 类型会限制结果的范围,要么是127,要么是255,这取决于你的C编译器是默认使用 signed char 还是 unsigned char。在C语言中,char 是一种整数类型,你不需要用 ord() 来获取它的整数值。

你原来的代码没有提到这个限制。要注意,如果一个 char 溢出,它会默默发生,这样代码就会产生错误的结果——比如127加1会变成-128(有符号的);255加1会变成0(无符号的)。

你没有回复我对你原问题的评论:“你的字符串的(a)最大长度和(b)平均长度是多少?如果这两个字符串完全不相似,真的需要做O(M*N)的复杂度吗?”……请现在回答这个问题(编辑你的问题);如果你当时回答了这个问题,那么你就能得到答案了。

更新:再次阅读原帖,我发现了一个问题:读取的代码

m1, m2 = m2, m1
strcpy( m3, m2 )

在三个方面是错误的:(1)它没有正确地打乱行(应该在交换 m1m2 之前使用 strcpy()) (2)strcpy() 不会复制第一个空字符(零字节)之后的内容 (3)其实不需要复制任何东西,只需要打乱指针即可。

m3, m2, m1 = m2, m1, m3

撰写回答