我正在阅读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
(整数)对象。