Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   Re: variable length array (http://www.velocityreviews.com/forums/t313775-re-variable-length-array.html)

Dan Pop 06-24-2003 02:30 PM

Re: variable length array
 
In <3ef49249$0$5973$afc38c87@news.optusnet.com.au> "Simon Biber" <sbiber@optushome.com.au> writes:

>"Dan Pop" <Dan.Pop@cern.ch> wrote:
>> -W triggers often undesirable warnings (that's why they
>> haven't been included in -Wall in the first place)

>
>The warnings triggered by -W are often more stylistic things,
>or reminders that some practise may be a bit dangerous in some
>situations (even if in the specific case it is actually correct).
>I quite like those warnings, and prefer to modify my code to work
>around them rather than disable them, wherever possible.


I find them a nuisance and see no good reason for working around them.
The following is a trivial example where the compiler should trust the
programmer:

fangorn:~/tmp 336> cat test.c
#include <string.h>

void foo(int arg)
{
int i;
for (i = 0; i < strlen("abcde"); i++) /* do something */ ;
}
fangorn:~/tmp 337> gcc -c -Wall test.c
fangorn:~/tmp 338> gcc -c -Wall -W test.c
test.c: In function `foo':
test.c:6: warning: comparison between signed and unsigned
test.c:3: warning: unused parameter `arg'

I can see NO good reason for doing something with arg to keep -W silent
and I cannot drop it from the function interface (which is externally
imposed). Likewise, I don't want to declare i as unsigned for the *sole*
reason of shutting up -W (or cast the return value of strlen). I only
use unsigned variables when I have a good reason for that, because of
reasons discussed in a different thread.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Dan.Pop@ifh.de

Neil Cerutti 06-24-2003 03:13 PM

Re: variable length array
 
In article <bd9n9g$4j3$2@sunnews.cern.ch>, Dan Pop wrote:
> In <3ef49249$0$5973$afc38c87@news.optusnet.com.au> "Simon
> Biber" <sbiber@optushome.com.au> writes:
>>The warnings triggered by -W are often more stylistic things,
>>or reminders that some practise may be a bit dangerous in some
>>situations (even if in the specific case it is actually correct).
>>I quite like those warnings, and prefer to modify my code to work
>>around them rather than disable them, wherever possible.

>
> I find them a nuisance and see no good reason for working around them.
> The following is a trivial example where the compiler should trust the
> programmer:
>
> fangorn:~/tmp 336> cat test.c
> #include <string.h>
>
> void foo(int arg)
> {
> int i;
> for (i = 0; i < strlen("abcde"); i++) /* do something */ ;
> }
> fangorn:~/tmp 337> gcc -c -Wall test.c
> fangorn:~/tmp 338> gcc -c -Wall -W test.c
> test.c: In function `foo':
> test.c:6: warning: comparison between signed and unsigned
> test.c:3: warning: unused parameter `arg'
>
> I can see NO good reason for doing something with arg to keep
> -W silent and I cannot drop it from the function interface
> (which is externally imposed).


It's too bad it's illegal to omit the identifier in such cases.
Given that, I agree the warning is annoying in this case.

But an externally imposed function interface that requires
useless parameters is arguably the real cause of this particular
annoyance.

> Likewise, I don't want to declare i as unsigned for the *sole*
> reason of shutting up -W (or cast the return value of strlen).
> I only use unsigned variables when I have a good reason for
> that, because of reasons discussed in a different thread.


Your strlen usage example is perhaps too academic. The following
is equivalent, and evinces no such warning:

void foo(int arg)
{
int i;
for (i = 0; i < 5; i++) /* do something */ ;
}

--
Neil Cerutti

Zoran Cutura 06-24-2003 03:40 PM

Re: variable length array
 
Neil Cerutti <horpner@yahoo.com> wrote:
....
> Your strlen usage example is perhaps too academic. The following
> is equivalent, and evinces no such warning:
>
> void foo(int arg)
> {
> int i;
> for (i = 0; i < 5; i++) /* do something */ ;
> }
>


I don't see how Dan's example is academic or how yours is less academic.

sizeof array / sizeof *array

from my point of view is a somewhat often used term especially in for
or while loops which yields a unsigned integral value and comparing i
against it issues the warning Dan showed. I certainly do have a lot of
such comparisons in my programs and often either cast or declare i as
unsigned only for that reason.
--
Z (Zoran.Cutura@daimlerchrysler.com)
"LISP is worth learning for the profound enlightenment experience
you will have when you finally get it; that experience will make you
a better programmer for the rest of your days." -- Eric S. Raymond

Richard Heathfield 06-24-2003 06:44 PM

Re: variable length array
 
Neil Cerutti wrote:

<snip>
>
> Here's a slightly less trivial example, that allows me to make my
> point:
>
> void foo(int arg, char *s)
> {
> int i; /* wrong */
> for (i = 0; i < strlen(s); ++i) do_something(s[i]);
> }
>
> Using this example, it becomes possible to say that i ought to be
> of type size_t, making it's range equal to strlen's range.


And so it should. But don't you think it's better to move the strlen out of
the loop?

--
Richard Heathfield : binary@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton

Neil Cerutti 06-24-2003 06:55 PM

Re: variable length array
 
In article <3ef89a27@news2.power.net.uk>, Richard Heathfield wrote:
> Neil Cerutti wrote:
>
><snip>
>> Here's a slightly less trivial example, that allows me to make
>> my point:
>>
>> void foo(int arg, char *s)
>> {
>> int i; /* wrong */
>> for (i = 0; i < strlen(s); ++i) do_something(s[i]);
>> }
>>
>> Using this example, it becomes possible to say that i ought to
>> be of type size_t, making it's range equal to strlen's range.

>
> And so it should. But don't you think it's better to move the
> strlen out of the loop?


Yes.

--
Neil Cerutti

karl malbrain 06-24-2003 07:25 PM

Re: variable length array
 
"Richard Heathfield" <invalid@address.co.uk.invalid> wrote in message
news:3ef89a27@news2.power.net.uk...
> Neil Cerutti wrote:
>
> <snip>
> >
> > Here's a slightly less trivial example, that allows me to make my
> > point:
> >
> > void foo(int arg, char *s)
> > {
> > int i; /* wrong */
> > for (i = 0; i < strlen(s); ++i) do_something(s[i]);
> > }
> >
> > Using this example, it becomes possible to say that i ought to be
> > of type size_t, making it's range equal to strlen's range.

>
> And so it should. But don't you think it's better to move the strlen out

of
> the loop?


Actually, it's better to remove strlen completely:

for( i = 0; s[i]; i++ )
do_something(s[i]);

karl m



Zoran Cutura 06-25-2003 06:06 AM

Re: variable length array
 
Simon Biber <sbiber@optushome.com.au> wrote:
> "Dan Pop" <Dan.Pop@cern.ch> wrote:
>> "Simon Biber" <sbiber@optushome.com.au> wrote:
>> > The warnings triggered by -W are often more stylistic things,
>> > or reminders that some practise may be a bit dangerous in
>> > some situations (even if in the specific case it is actually
>> > correct). I quite like those warnings, and prefer to modify
>> > my code to work around them rather than disable them,
>> > wherever possible.

>>
>> I find them a nuisance and see no good reason for working
>> around them. The following is a trivial example where the
>> compiler should trust the programmer:
>>
>> fangorn:~/tmp 336> cat test.c
>> #include <string.h>
>>
>> void foo(int arg)
>> {
>> int i;
>> for (i = 0; i < strlen("abcde"); i++) /* do something */ ;
>> }
>> fangorn:~/tmp 337> gcc -c -Wall test.c
>> fangorn:~/tmp 338> gcc -c -Wall -W test.c
>> test.c: In function `foo':
>> test.c:6: warning: comparison between signed and unsigned

>
> There is very good reason for the warning here as it has
> uncovered a potential bug in your code. If the value
> returned by strlen is greater than INT_MAX, your program
> has undefined behaviour due to overflow.


I don't see any potential for overflow in the above code.
As strlen returns a size_t which definitly is a unsigned integer type
and i is of signed int some conversion will take place. If size_t where
lower in rank than int (I'm not entirely sure about whether it would be
allowed to be lower in rank than int) the size_t value would be
converted to an int due to usual arithmetic conversions if all values of
size_t could be represented within int. If not, both values would be
converted to unsigned int and even if i where negativ overflow would not
occur.

If size_t is bigger in rank than i will equally be converted to the same
type and again overlfow can not happen. So I conclude there is no
potential fro overflow and thereby UB in this code.

But probably I've missed something.

--
Z (Zoran.Cutura@daimlerchrysler.com)
"LISP is worth learning for the profound enlightenment experience
you will have when you finally get it; that experience will make you
a better programmer for the rest of your days." -- Eric S. Raymond

Christian Bau 06-25-2003 06:56 AM

Re: variable length array
 
In article <bdbe4o$s58$1@news.sns-felb.debis.de>,
Zoran Cutura <zoran.cutura@daimlerchrysler.com> wrote:

> >> fangorn:~/tmp 336> cat test.c
> >> #include <string.h>
> >>
> >> void foo(int arg)
> >> {
> >> int i;
> >> for (i = 0; i < strlen("abcde"); i++) /* do something */ ;
> >> }

> I don't see any potential for overflow in the above code.
> As strlen returns a size_t which definitly is a unsigned integer type
> and i is of signed int some conversion will take place. If size_t where
> lower in rank than int (I'm not entirely sure about whether it would be
> allowed to be lower in rank than int) the size_t value would be
> converted to an int due to usual arithmetic conversions if all values of
> size_t could be represented within int. If not, both values would be
> converted to unsigned int and even if i where negativ overflow would not
> occur.
>
> If size_t is bigger in rank than i will equally be converted to the same
> type and again overlfow can not happen. So I conclude there is no
> potential fro overflow and thereby UB in this code.


Apart from the fact that strlen ("abcde") is five and no overflow can
happen, if "abcde" were replaced by a string with 33000 characters and
int = 16 bit then the i++ will eventually overflow.

But I suspect the compiler complains about the fact that if i is
negative (which it can't be in this example) then i is less than strlen
("abcde") but (i < strlen ("abcde")) could produce a result of zero.
Strictly according to the C rules, but wrong.

Simon Biber 06-25-2003 07:00 AM

Re: variable length array
 
"Zoran Cutura" <zoran.cutura@daimlerchrysler.com> wrote:
> Simon Biber <sbiber@optushome.com.au> wrote:
> > "Dan Pop" <Dan.Pop@cern.ch> wrote:
> >> #include <string.h>
> >>
> >> void foo(int arg)
> >> {
> >> int i;
> >> for (i = 0; i < strlen("abcde"); i++)
> >> /* do something */ ;
> >> }
> >> fangorn:~/tmp 337> gcc -c -Wall test.c
> >> fangorn:~/tmp 338> gcc -c -Wall -W test.c
> >> test.c: In function `foo':
> >> test.c:6: warning: comparison between signed and unsigned

> >
> > There is very good reason for the warning here as it has
> > uncovered a potential bug in your code. If the value
> > returned by strlen is greater than INT_MAX, your program
> > has undefined behaviour due to overflow.

>
> I don't see any potential for overflow in the above code.
>
> As strlen returns a size_t which definitly is a unsigned
> integer type and i is of signed int some conversion will
> take place. If size_t were lower in rank than int (I'm
> not entirely sure about whether it would be allowed to
> be lower in rank than int) the size_t value would be
> converted to an int due to usual arithmetic conversions
> if all values of size_t could be represented within int.
> If not, both values would be converted to unsigned int
> and even if i where negativ overflow would not occur. If
> size_t is bigger in rank than i will equally be converted
> to the same type and again overlfow can not happen. So I
> conclude there is no potential fro overflow and thereby
> UB in this code.


The overflow is not in the conversion. In fact, conversions
of values outside the range of the target type are never
considered as `overflow'. The semantics are quite different.

(1) In the case of converting to an unsigned integer type,
the results are strictly defined to wrap around, as if
the maximum value plus one was added or subtracted
until within the range.

(2) In the case of converting to a signed integer type, the
resulting value is implementation defined, or (in C99)
an implementation-defined signal may be raised. However,
there is not an outright undefined behaviour.

(3) When the result of an unsigned arithmetic operation
doesn't fit within the range, unsigned types never
overflow -- they wrap around.

(4) On the other hand, when computing an arithmetic overflow
in a signed type there is immediate undefined behaviour.
The standard doesn't specify an implementation-defined
result or signal.

In practise, of course, many 2's complement implementations
behave exactly the same for all four cases, which leads to
confusion.

> But probably I've missed something.


If the value returned by strlen is greater than INT_MAX,
the comparison will always be true. Then after some time
while incrementing through the loop, i will equal INT_MAX,
it will be incremented once more, and overflow will occur.
This is arithmetic overflow in a signed type, not a
conversion, and so it is undefined behaviour.

--
Simon.



Richard Bos 06-25-2003 08:01 AM

Re: variable length array
 
Richard Heathfield <invalid@address.co.uk.invalid> wrote:

> Neil Cerutti wrote:
>
> <snip>
> >
> > Here's a slightly less trivial example, that allows me to make my
> > point:
> >
> > void foo(int arg, char *s)
> > {
> > int i; /* wrong */
> > for (i = 0; i < strlen(s); ++i) do_something(s[i]);
> > }
> >
> > Using this example, it becomes possible to say that i ought to be
> > of type size_t, making it's range equal to strlen's range.

>
> And so it should. But don't you think it's better to move the strlen out of
> the loop?


No. If do_something() can set s[i] to '\0', the loop will abort next
time, and this effect may have been intentional. If do_something() never
changes s[i], or rather, never sets it to the null character, the
compiler can figure that out and optimise the strlen() call away itself.
And leaving the strlen() where it is makes for a semantically better
(read: more naturally expressed) program.

Richard


All times are GMT. The time now is 10:43 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.