" strlen的(S1) - 的strlen(S2)"是从不小于零的 [英] "strlen(s1) - strlen(s2)" is never less than zero

查看:199
本文介绍了" strlen的(S1) - 的strlen(S2)"是从不小于零的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在写一个需要字符串的比较频繁的一个C程序的长度,所以我写了下面的辅助功能:

I am currently writing a C program that requires frequent comparisons of string lengths so I wrote the following helper function:

int strlonger(char *s1, char *s2) {
    return strlen(s1) - strlen(s2) > 0;
}

我注意到,即使在 S1 S2 长度较短的函数返回true。有人可以解释这种奇怪的行为?

I have noticed that the function returns true even when s1 has shorter length than s2. Can someone please explain this strange behavior?

推荐答案

什么你遇到一些奇怪的行为处理包含符号和无符号数量前pressions时中出现的温度。

What you've come across is some peculiar behavior that arises in C when handling expressions that contain both signed and unsigned quantities.

当其中一个操作数签署执行操作,另一个是无符号,C将隐式转换签订参数无符号和执行假定数字的操作是负数。这种约定往往导致关系运算符,如不直观行为< >

When an operation is performed where one operand is signed and the other is unsigned, C will implicitly convert the signed argument to unsigned and perform the operations assuming the numbers are nonnegative. This convention often leads to nonintuitive behavior for relational operators such as < and >.

对于您的辅助函数,注意,由于的strlen 返回类型为为size_t (无符号数)的差异,比较都使用计算算术符号。当 S1 短于 S2 ,差异的strlen(S1) - 的strlen(S2) 应该是否定的,而是成为大的,无符号数,这是比 0 更大。因此,

Regarding your helper function, note that since strlen returns type size_t (an unsigned quantity), the difference and the comparison are both computed using unsigned arithmetic. When s1 is shorter than s2, the difference strlen(s1) - strlen(s2) should be negative, but instead becomes a large, unsigned number, which is greater than 0. Thus,

return strlen(s1) - strlen(s2) > 0;

收益 1 即使 S1 S2 。要解决你的函数,用这个code来代替:

returns 1 even if s1 is shorter than s2. To fix your function, use this code instead:

return strlen(s1) > strlen(s2);

欢迎到C的奇妙世界! :)

Welcome to the wonderful world of C! :)

由于这个问题最近收到了很多关注,我想提供一些(简单)的例子,只是为了确保我正在对面的想法。我会认为我们是一个32位机采用补重presentation工作。

Since this question has recently received a lot of attention, I'd like to provide a few (simple) examples, just to ensure that I am getting the idea across. I will assume that we are working with a 32-bit machine using two's complement representation.

重要的概念在C无符号/签名的变量时明白的是,的如果有是无符号的组合,并在一个单一的前pression签约量,签约值被隐式转换为无符号

The important concept to understand when working with unsigned/signed variables in C is that if there is a mix of unsigned and signed quantities in a single expression, signed values are implicitly cast to unsigned.

考虑下面的前pression:

Consider the following expression:

-1 < 0U

由于第二个操作数是无符号的,第一个是隐式转换的无符号,因此前pression相当于比较,

Since the second operand is unsigned, the first one is implicitly cast to unsigned, and hence the expression is equivalent to the comparison,

4294967295U < 0U

这当然是假的。这可能不是您所期望的行为。

which of course is false. This is probably not the behavior you were expecting.

考虑以下code,试图总结各种元素的数目由参数给出一个数组 A ,元素长度

Consider the following code that attempts to sum the elements of an array a, where the number of elements is given by parameter length:

int sum_array_elements(int a[], unsigned length) {
    int i;
    int result = 0;

    for (i = 0; i <= length-1; i++) 
        result += a[i];

    return result;
}

此功能旨在演示的错误是多么容易出现由于隐式转换从符号到无符号。这似乎很自然地传递参数长度未签名的;毕竟,谁真的愿意使用负的长度?停止标准 I&LT; =长度-1 似乎也很直观。然而,当参数运行长度等于 0 ,这两者的结合产生了一个意想不到的结局。

This function is designed to demonstrate how easily bugs can arise due to implicit casting from signed to unsigned. It seems quite natural to pass parameter length as unsigned; after all, who would ever want to use a negative length? The stopping criterion i <= length-1 also seems quite intuitive. However, when run with argument length equal to 0, the combination of these two yields an unexpected outcome.

由于参数长度是无符号数,计算 0-1 使用无符号运算,这相当于执行模加。其结果是随后的 UMAX 的。在&下; = 比较还使用一个无符号的比较进行的,并且由于任何数量小于或等于<青霉> UMAX 的,比较总是成立。因此,code将试图访问阵列中的无效元素 A

Since parameter length is unsigned, the computation 0-1 is performed using unsigned arithmetic, which is equivalent to modular addition. The result is then UMax. The <= comparison is also performed using an unsigned comparison, and since any number is less than or equal to UMax, the comparison always holds. Thus, the code will attempt to access invalid elements of array a.

在code可以通过声明长度是一个 INT ,或通过改变固定在循环测试为 I&LT;长度

The code can be fixed either by declaring length to be an int, or by changing the test of the for loop to be i < length.

我不希望在这里说出什么太有争议,但这里有一些我经常坚持,当我写程序用C的规则。

I don't want to state anything too controversial here, but here are some of the rules I often adhere to when I write programs in C.


  • 不要的使用仅仅因为一个数字是负数。这是很容易犯错误,而这些错误有时是令人难以置信的微妙(如例所示#2)。

  • DON'T use just because a number is nonnegative. It is easy to make mistakes, and these mistakes are sometimes incredibly subtle (as illustrated in Example #2).

执行模运算时DO 的使用。

DO use when performing modular arithmetic.

DO 的使用位何时重新present集中使用。这往往是方便,因为它可以让你无符号扩展执行逻辑右移。

DO use when using bits to represent sets. This is often convenient because it allows you to perform logical right shifts without sign extension.

当然,也有可能是你决定去反对这些规则的情况。但多数情况下不是,以下这些建议将使您的code更容易使用和更不容易出错。

Of course, there may be situations in which you decide to go against these "rules". But most often than not, following these suggestions will make your code easier to work with and less error-prone.

这篇关于&QUOT; strlen的(S1) - 的strlen(S2)&QUOT;是从不小于零的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆