[Issue 8874] New: Possible warning for always true/always false comparisons on unsigned values
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Mon Oct 22 15:33:13 PDT 2012
http://d.puremagic.com/issues/show_bug.cgi?id=8874
Summary: Possible warning for always true/always false
comparisons on unsigned values
Product: D
Version: D2
Platform: All
OS/Version: All
Status: NEW
Keywords: diagnostic
Severity: enhancement
Priority: P2
Component: DMD
AssignedTo: nobody at puremagic.com
ReportedBy: bearophile_hugs at eml.cc
--- Comment #0 from bearophile_hugs at eml.cc 2012-10-22 15:33:11 PDT ---
This small C program solves a common Subset sum problem:
http://rosettacode.org/wiki/Subset_sum_problem
// C code starts here ------------------------
#include <stdio.h>
#include <stdlib.h>
typedef struct { char* data; int weight; } item;
typedef struct { int sum; unsigned int mask; } sum_t;
item em[] = {
{"alliance", -624}, {"archbishop", -915}, {"balm", 397},
{"bonnet", 452}, {"brute", 870}, {"centipede", -658},
{"cobol", 362}, {"covariate", 590}, {"departure", 952},
{"deploy", 44}, {"diophantine", 645}, {"efferent", 54},
{"elysee", -326}, {"eradicate", 376}, {"escritoire", 856},
{"exorcism", -983}, {"fiat", 170}, {"filmy", -874},
{"flatworm", 503}, {"gestapo", 915}, {"infra", -847},
{"isis", -982}, {"lindholm", 999}, {"markham", 475},
{"mincemeat", -880}, {"moresby", 756}, {"mycenae", 183},
{"plugging", -266}, {"smokescreen", 423}, {"speakeasy", -745},
{"vein", 813}
};
#define N (sizeof(em)/sizeof(em[0]))
int cmp_sums(const void *a, const void *b)
{
return ((sum_t*)a)->sum - ((sum_t*)b)->sum;
}
sum_t *mksums(item *p, int n, int shift)
{
sum_t *r = malloc(sizeof(*r) * (1 << n));
int i;
for (i = 0; i < n; i++)
r[1<<i].sum = p[i].weight;
r[0].mask = 0, r[0].sum = 0;
for (i = 1; i < 1<<n; i++) {
unsigned int b = i & -(int)i;
r[i].mask = i << shift;
r[i].sum = r[i & ~b].sum + r[b].sum;
}
qsort(r, 1<<n, sizeof(*r), cmp_sums);
return r;
}
int main(void)
{
int n1 = N / 2, n2 = N - n1, sols = 0;
int i, j, i1, j1;
#define SHOW_ALL 1
#define N1 (1 << n1)
#define N2 (1 << n2)
sum_t *l = mksums(em, n1, 0),
*r = mksums(em + n1, n2, n1);
void showmask(unsigned int mask)
{
unsigned int m;
for (m = 0; (1<<m) <= mask; m++) {
if (mask & (1<<m))
printf("(%s,%d) ", em[m].data, em[m].weight);
}
if (mask) puts("");
}
int printlist() {
int x, y, s = (i1 - i) * (j - j1);
if (!l[i].sum) s--;
if (SHOW_ALL)
for (x = i; x < i1; x++)
for (y = j; y > j1; y--)
showmask(l[x].mask | r[y].mask);
return s;
}
i = 0, j = N2 - 1;
while (1) {
while (l[i].sum + r[j].sum) {
while (i < N1 && l[i].sum + r[j].sum < 0) i++;
while (j >= 0 && l[i].sum + r[j].sum > 0) j--;
if (i >= N1 || j < 0) break;
}
if (i >= N1 || j < 0) break;
for (i1 = i + 1; i1 < N1 && l[i1].sum == l[i].sum; i1++);
for (j1 = j - 1; j1 >= 0 && r[j1].sum == r[j].sum; j1--);
sols += printlist();
i = i1, j = j1;
}
printf("zero sums: %d\n", sols);
return 0;
}
// C code ends here ------------------------
The i, j, i1, j1 variables are used as array indexes, so to "improve" the code
I am willing to try replacing the line of code:
int i, j, i1, j1;
With:
size_t i, j, i1, j1;
Compiling with GCC 4.7.1, using "-Wall -Wextra", it produces the warnings:
temp.c: In function 'showmask':
temp.c:59:28: warning: comparison between signed and unsigned integer
expressions [-Wsign-compare]
temp.c: In function 'printlist':
temp.c:71:27: warning: comparison between signed and unsigned integer
expressions [-Wsign-compare]
temp.c:72:27: warning: comparison between signed and unsigned integer
expressions [-Wsign-compare]
temp.c: In function 'main':
temp.c:80:22: warning: comparison between signed and unsigned integer
expressions [-Wsign-compare]
temp.c:81:13: warning: comparison of unsigned expression >= 0 is always true
[-Wtype-limits]
temp.c:82:19: warning: comparison between signed and unsigned integer
expressions [-Wsign-compare]
temp.c:82:13: warning: comparison of unsigned expression < 0 is always false
[-Wtype-limits]
temp.c:84:15: warning: comparison between signed and unsigned integer
expressions [-Wsign-compare]
temp.c:84:9: warning: comparison of unsigned expression < 0 is always false
[-Wtype-limits]
temp.c:86:29: warning: comparison between signed and unsigned integer
expressions [-Wsign-compare]
temp.c:87:9: warning: comparison of unsigned expression >= 0 is always true
[-Wtype-limits]
Here the warning messages generated by "-Wtype-limits" save me from those bugs
caused by refactoring.
With DMD 2.061alpha using the "-wi" compilation switch this code gives no
warning messages:
// D code
int foo(uint x, uint y) {
uint count = 0;
if (x >= 0)
count++;
if (y < 0)
count++;
return count;
}
void main() {}
In this little foo() function it's easy to see the problems, but in a large
function it's more easy to miss the mistake of using unsigned x and y with
those comparisons that are always false or always true.
So consider the possibility of adding such warning to D/DMD.
--
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
More information about the Digitalmars-d-bugs
mailing list