我在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。
那么问题出在哪里?
答案 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
的所有组合定义操作。
而不是int
和from
的{{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;,而是变量的最大值。