-1不小于12?

时间:2015-10-05 14:01:42

标签: c string substring assert

我在C(substring)中有一个小程序:

char *str_sub(char *string, int from, int to) {
    assert(to < 0 || from < to);

    if (!(to < strlen(string))) {
        printf("%d %ld\n", to, strlen(string));
    }

    assert(from < strlen(string) && to < strlen(string));

    char *result = (char *) calloc(to - from + 1, 1);

    memcpy(result, &string[from], to);
    result[to] = '\0';

当我将-1传递给to时,我想让函数与字符串的其余部分匹配,但这并不重要。你看到第二个断言吗?当我将-1传递给to时,它会引发错误,并且在上述条件下它也会显示false,但它只是-1和12,正如我们从学校所知, - 1&lt; 12。

那么问题出在哪里?

4 个答案:

答案 0 :(得分:1)

您正在比较具有不同签名的变量,因此-1的表示在它们之间并不一致。另请参阅评论中引用的@Shafik Yaghmour的答案。

我可以像这样显示编译器的警告:

$ clang -Wsign-compare -c sign.c
sign.c:9:14: warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare]
    if (!(to < strlen(string))) {
          ~~ ^ ~~~~~~~~~~~~~~
sign.c:13:17: warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare]
    assert(from < strlen(string) && to < strlen(string));
           ~~~~ ^ ~~~~~~~~~~~~~~
/usr/include/assert.h:89:5: note: expanded from macro 'assert'
  ((expr)                                                               \
    ^
sign.c:13:40: warning: comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare]
    assert(from < strlen(string) && to < strlen(string));
                                    ~~ ^ ~~~~~~~~~~~~~~
/usr/include/assert.h:89:5: note: expanded from macro 'assert'
  ((expr)                                                               \
    ^

$ cat sign.c
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

char *str_sub(char *string, int from, int to) {
    assert(to < 0 || from < to);

    if (!(to < strlen(string))) {
        printf("%d %ld\n", to, strlen(string));
    }

    assert(from < strlen(string) && to < strlen(string));

    char *result = (char *) calloc(to - from + 1, 1);

    memcpy(result, &string[from], to);
    result[to] = '\0';

    return result;
}

答案 1 :(得分:1)

许多人说,to < strlen(string)比较(size_t)-1 < strlen(string)。由于size_t是一些无符号类型,(size_t)-1是一个很大的正值,这种比较经常失败。 @Shafik Yaghmour

要解决此问题:请考虑size_t

char *str_sub(char *string, int from, int to) {
    assert(to < 0 || from < to);
    assert(from >= 0);

    size_t length = strlen(string);
    size_t uto = to < 0 ? length : to; 

    assert(from < uto);

    if (!(uto < strlen(string))) {
        printf("%zu %zu\n", uto, strlen(string));
    }

    assert(from < length && uto < length);

    char *result = malloc(uto - from + 1);

    // memcpy(result, &string[from], to);
    memcpy(result, &string[from], uto - from);
    // result[to] = '\0';
    result[uto - from] = '\0';
    return result;
}

注意:而不是所有这些assert(),建议为from,to的所有组合定义操作。

而不是intfrom的{​​{1}},而是使用to并创建size_t。例如:

#define  MATCH_REST ((size_t)-1)

答案 2 :(得分:0)

[HttpPost] [ValidateAntiForgeryToken] public ActionResult Index([Bind(Include = "Id,Child1GiftTypeNeed")] HGProgram hgProgram) { if (ModelState.IsValid) { //Save to my database db.HGPrograms.Add(hgProgram); db.SaveChanges(); } } 返回python migrate.py syncdb (无符号相关)变量,在进行任何比较之前,两个变量必须具有相同的类型。因此,其中一个必须投射到另一个。

在您的示例中,我确定strlen已经转换为size_t,导致溢出(-1),并且您可能正在将to与最大可表示无符号整数进行比较(溢出的可能结果)。

所以,解决方案是:

unsigned

或者,为了避免重新计算:

strlen(string)

或者,为了安全铸件,需要太长时间char *str_sub(char *string, int from, int to) { assert(to < 0 || from < to); if (!(to < (int)strlen(string))) { printf("%d %ld\n", to, strlen(string)); } assert(from < strlen(string) && to < (int)strlen(string)); char *result = (char *) calloc(to - from + 1, 1); memcpy(result, &string[from], to); result[to] = '\0'; (感谢评论,@ chux):

char *str_sub(char *string, int from, int to) {
  int length = strlen(string);

  assert(to < 0 || from < to);

  if (!(to < length)) {
    printf("%d %ld\n", to, length);
  }

  assert(from < length && to < length);

  char *result = (char *) calloc(to - from + 1, 1);

  memcpy(result, &string[from], to);
  result[to] = '\0';

答案 3 :(得分:0)

比较运算符假定您比较的两个变量属于同一类型。这不是这种情况,&#34; -1&#34;的二进制表示。 unsigned作为有符号变量并非#34; -1&#34;,而是变量的最大值。