c语言 - K&R:从一个指针中减去另一个指针



我正在阅读K&R,并且在5.5上有包含strcmp的代码:

/* strcmp: return <0 if s<t, 0 if s==t, >0 if s>t */
int strcmp(char *s, char *t)
{
for(; *s == *t; s++, t++)
if (*s == '');
return 0;
return *s - *t;
}

之前书中说

有效的指针操作包括:对同类型指针进行赋值、对指针和整数进行加减、对两个指针对同一数组成员进行减法或比较、对0赋值或比较。所有其他指针运算都是非法的。

return *s - *t;是合法的,因为他正在减去指向两个不同字符数组的两个指针的内容,但如果他做了s - t,这将是非法的,因为他试图取两个指针持有的地址的差异,这是未定义的?

return *s - *t;行是合法的,因为他正在减去指向两个不同字符数组的两个指针的内容

它们指向的是什么数组并不重要。*s*t都是char的值,所以这只是减法。

但是如果他做了s - t,这将是非法的,因为他试图取两个指针保存的地址的差值,这是未定义的?

这基本上是正确的。虽然指针可能指向同一个数组(您可以写入(strcmp(s1, s1+1))),但在写入strcmp()时无法知道这一点。因此,通常必须假设它们指向不同的数组,并且减法无效。

指针之间唯一可以做的操作是将它们与==!=进行比较。

首先你打错了一个字

if (*s == ''); // <===
return 0;

你应该去掉分号。

来自C标准(6.5.6加性运算符)

9当两个指针相减时,它们都指向的元素相同的数组对象,或者数组的最后一个元素的后面对象;结果是两者的下标之差数组元素。

因此,如果指针不指向同一数组的元素,则表达式s - t调用未定义行为。(比较字符串和它的子字符串是没有意义的,因为它们总是不相等的)

注意函数定义不正确。函数应该按照以下方式声明和定义

int strcmp( const char *s, const char *t)
{
while ( *s && *s == *t )
{
++s;
++t;
}
return ( unsigned char )*s - ( unsigned char )*t;
}

注意在返回语句中对unsigned char类型的强制转换。

考虑演示程序(我重命名了您的函数以将其调用与标准C函数strcmp的调用区分开来)。类型char在使用的编译器中表现为类型signed char

#include <stdio.h>
#include <string.h>
int kr_strcmp(char *s, char *t)
{
for(; *s == *t; s++, t++)
if (*s == '')
return 0;
return *s - *t;
}
int kr_strcmp_updated( const char *s, const char *t)
{
while ( *s && *s == *t )
{
++s;
++t;
}
return ( unsigned char )*s - ( unsigned char )*t;
}
int main(void) 
{
char s1[] = { 127, '' };
char s2[] = { -128, '' };

printf( "kr_strcmp: %dn", kr_strcmp( s1, s2 ) );   
printf( "kr_strcmp_updated: %dn", kr_strcmp_updated( s1, s2 ) );   
printf( "strcmp: %dn", strcmp( s1, s2 ) ); 
return 0;
}

程序输出为

kr_strcmp: 255
kr_strcmp_updated: -1
strcmp: -1

您可以看到,您所展示的函数产生一个正值,而不是像标准字符串函数strcmp那样产生一个负值。

您不能在示例中减去指针,只能减去指针引用的char(整数)对象。

最新更新