View mode: basic / threaded / horizontal-split · Log in · Help
June 11, 2012
Some programming mistakes
An article, "Eight C++ programming mistakes the compiler won't 
catch":
http://pixelstech.net/article/index.php?id=1333893320

Its Reddit thread:
http://www.reddit.com/r/cpp/comments/s0o99/eight_c_programming_mistakes_the_compiler_wont/


Some quotations from the article, valid for D too:

> 2) Integer division
> 
> Many new programmers attempt to do the following:
> 
> int nX = 7;
> int nY = 2;
> float fValue = nX / nY;  // fValue = 3 (not 3.5!)
> 
> The underlying assumption here is that nX / nY will result in a
> floating point division because the result is being assigned to
> a floating point value. However, this is not the case.

GCC with -Wconversion finds that problem, but maybe with too much 
noise:

int main() {
    float fX = 7.0;
    int nY = 2;
    float fValue = fX / nY;
    return 0;
}

...>gcc -Wconversion test.c -o test
test.c: In function 'main':
test.c:4:5: warning: conversion to 'float' from 'int' may alter 
its value [-Wconversion]



> 4) Mixing signed and unsigned values
> 
> int nX;
> unsigned int nY;
> 
> if (nX - nY < 0)
>     // do something

GCC with -Wconversion finds it.
There are more interesting cases with mixing short with uint, etc.



> 6) Side effects in compound expressions or function calls
> 
> int foo(int x)
> {
> return x;
> }
> 
> int main()
> {
>     int x = 5;
>     std::cout << foo(x) * foo(++x);
> }
> 
> A good rule of thumb is to put any operator that
> causes a side effect in it’s own statement.

Bye,
bearophile
June 11, 2012
Re: Some programming mistakes
On 11 June 2012 12:59, bearophile <bearophileHUGS@lycos.com> wrote:
> An article, "Eight C++ programming mistakes the compiler won't catch":
> http://pixelstech.net/article/index.php?id=1333893320
>
> Its Reddit thread:
> http://www.reddit.com/r/cpp/comments/s0o99/eight_c_programming_mistakes_the_compiler_wont/
>
>
> Some quotations from the article, valid for D too:
>
>> 2) Integer division
>>
>> Many new programmers attempt to do the following:
>>
>> int nX = 7;
>> int nY = 2;
>> float fValue = nX / nY;  // fValue = 3 (not 3.5!)
>>
>> The underlying assumption here is that nX / nY will result in a
>> floating point division because the result is being assigned to
>> a floating point value. However, this is not the case.
>
>
> GCC with -Wconversion finds that problem, but maybe with too much noise:
>
> int main() {
>    float fX = 7.0;
>    int nY = 2;
>    float fValue = fX / nY;
>    return 0;
> }
>
> ...>gcc -Wconversion test.c -o test
> test.c: In function 'main':
> test.c:4:5: warning: conversion to 'float' from 'int' may alter its value
> [-Wconversion]
>
>
>

This is a valid case that should be easy enough to detect.  Though I
will not be able to say for definite without looking under the hood.


>> 4) Mixing signed and unsigned values
>>
>> int nX;
>> unsigned int nY;
>>
>> if (nX - nY < 0)
>>    // do something
>
>
> GCC with -Wconversion finds it.
> There are more interesting cases with mixing short with uint, etc.
>
>
>

This was something that was done in early gdc D1. But the frontend
codegen now actually makes this impossible to detect in the backend
with the implicit cast()'s it puts in.

There was a pull request for this that was accepted, then taken out
because it broke too much of existing code left and right.


>> 6) Side effects in compound expressions or function calls
>>
>> int foo(int x)
>> {
>> return x;
>> }
>>
>> int main()
>> {
>>    int x = 5;
>>    std::cout << foo(x) * foo(++x);
>> }
>>
>> A good rule of thumb is to put any operator that
>> causes a side effect in it’s own statement.
>

Generally, compound statements and function parameters are evaluated
from left to right as the prime order of evaluation.  extern(C)
functions parameters are a notable exception of this and may not
follow the same convention, ie, in code like:  foo( bar(), baz() );
baz() may be evaluated first.

-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
Top | Discussion index | About this forum | D home