POV-Ray : Newsgroups : povray.off-topic : Teach yourself C++ in 21 days : Re: Days 1-5 Server Time
29 Jul 2024 12:26:59 EDT (-0400)
  Re: Days 1-5  
From: Invisible
Date: 17 Apr 2012 10:04:34
Message: <4f8d7872$1@news.povray.org>
On 17/04/2012 02:40 PM, Warp wrote:
> Orchid Win7 v1<voi### [at] devnull>  wrote:
>> Then there's a cryptic reference to the fact that iostream and
>> iostream.h aren't the same, but the differences are "subtle, exotic, and
>> beyond the scope of an introductory primer".
>
>    One is standard, the other isn't. What is there more to explain?

The book doesn't actually mention this fact. It seems to suggest that 
you just use whichever one you fancy. And then says something about "but 
we're going to use iostream.h for compatibility reasons".

So I'm presuming iostream is the standards-compliant one?

>> Anyway, apparently main() must always return int. It is against the ANSI
>> standard for it to return void. (No mention of it having parameters.
>> Indeed, even the return value is described as an "obscure feature which
>> we won't make use of".)
>
>    I don't think it would have been very hard to say something like "the
> return value is used by the operating system as a success/failure value"
> and then explain that 0 means success and other values can be used as a
> failure code. (It is actually important to know this especially when
> creating a command-line program. The return value of main() is
> significant.)

Yeah, an exit code is not exactly an "obscure feature". I can understand 
the book not using it, but that doesn't mean the same as being useless.

>> Then there's some mumbo-jumbo about how you can use cout "to do
>> addition", and how when you do count<<  8+5, then "8+5 is passed to
>> cout, but 13 is what is actually printed". Nice, clear explanation,
>> that. :-P
>
>    Actually "8+5" is not being passed to cout.

Quite. The text completely fails to explain what's /actually/ happening. 
A bit later on it starts talking about how "the compiler" calls XYZ when 
you do ABC. Obviously, the compiler doesn't call anything; it just 
generates code. :-P

> Anyways, it's not like it's important.

It is if you want to form an understanding of what the stuff you're 
typing in actually /means/. The text makes it sound like adding is 
somehow special to cout, which clearly it isn't. You can do this with 
/any/ function call.

>> And then it starts talking about types. Apparently C++ adds a new "bool"
>> type, which is supposed to be 1 byte.
>
>    I don't think the standard defines the size of bool. Most compilers
> probably make it 1.

I have a sinking feeling you're right.

>> Apparently "char" doesn't mean
>> character at all, it means a 1-byte integer (and by default, a signed one).
>
>    The standard only guarantees that sizeof(char) is 1, but not that char
> is 1 byte. (It is possible for char to be larger in some systems. It just
> means that everything else is then a multiple of that size.)
>
>    The standard also lets the signedness of char as implementation-defined.
> (In most practical systems it's signed.)

Oh... goodie.

>    (Curiously, "char" and "signed char" are two *different* types in C and
> C++ even if "char" is signed, while for example "int" and "signed int" are
> completely synonymous and the "signed" keyword is redundant in the latter
> case. This comes from the prehistoric dark ages of C.)

Wait... I didn't even know you could /do/ that! o_O

>    Nope. The standard does not say that. The only thing the standard says
> is that:
>
>      sizeof(char)<= sizeof(short)<= sizeof(int)<= sizeof(long)
>
> and that sizeof(char) = 1 (which does not mean "1 byte", but "1 indexable
> memory unit".)
>
>    (Yes, it is possible and standard-conforming for char to be as large
> as long.)
>
>    In practice in most 32-bit systems short will be 16 bits and int/long
> will be 32 bits. In most 64-bit systems it will be the same except that
> long will be 64 bits.
>
>    Curiously, the new standard specifically states that the new "long long"
> type has to be at least 64 bits. (The new standard also defines official
> typedefs for integrals of specific sizes.)

Ouch. My head.

>    "Never use int" is a silly thing to say.
>
>    If you need an integral that's the natural word size of the target system,
> use int. If you need an integral with a specific number of bits, use one
> of the new standard typedefs.

Now /that/ actually makes sense. Where are these typedefs located? Do 
you have to include them specifically, or...?

> Use "long long" for an integral of at least
> 64 bits (at least if your compiler supports C++11). There's no standard
> support for larger integrals (because they are not supported by CPUs).

Not supported _yet_. ;-)

>    C hackers don't want the extra clock cycle to initialize a variable
> which will be immediately assigned a new value anyways.

I figured.

>    As a side effect you get all kinds of weird behavior if you forget to
> initialize a variable.

Yeah, it's great, isn't it? ;-)

I had hoped for maybe a compile-time warning. I haven't actually tried 
it to see if I get one though...

(Java actually refuses to compile your code if it can't satisfy itself 
that /every/ variable is initialised. Which gets annoying when every 
variable /is/ initialised before use, but the compiler can't prove it...)

>> Apparently assigning a double to an int is only a /warning/, not a
>> compile-time error. The book helpfully fails to specify how the
>> conversion is actually done.
>
>    The integral part of the value is assigned to the int.

So... it always rounds towards zero?

>> is a perfectly valid statement in C++. On the other hand, it also means that
>
>>     while (x[i] = y[i--]) ;
>
>> is perfectly valid. You sick, sick people.
>
>    I think that's Undefined Behavior because the same variable is being
> modified and referenced more than once in the same expression.

Aren't expressions guaranteed to execute left-to-right?

>    Even if it isn't UB, better not do it like that.

But that's just it. All C programmers always code in this kind of style. 
It's part of what makes C so terrifying to try to read.

>> In most programming languages, performing division promotes integers to
>> reals. But not in C++, apparently.
>
>    C is a wrapper around assembly, and assembly supports integral division.
> Hence dividing integers performs integral division. Oftentimes you *want*
> integral division

Most languages seem to provide a separate operator for that. But sure, OK.

>> At this point, we
>> are told that there's two ways to convert something to an double:
>
>>     double x = (double)y;
>
>>     double x = static_cast<double>y;
>
>> Apparently the former is bad, and the latter is good. No indication as
>> to why, it just is.
>
>    The former casts *anything* into a double, while the latter casts only
> compatible types. (Which means that the latter will give you a compiler
> error if you try to cast from an incompatible type by mistake.)

Now why the hell they couldn't just /say/ that I don't know...

>> Next we learn that false=0, and true /= 0. (Christ, I'm /never/ going to
>> remember that!) Apparently there's a new bool type, but details are thin
>> as to what the exact significance of this is.
>
>    You are never going to remember that 0 is false?

I know that zero is one thing, and everything else is the other thing. 
But I always struggle to remember whether zero means true or false. The 
solution, of course, is to never ever use integers as bools.

>> Then we learn about if/then, if/then/else, and finally ?: is
>> demonstrated, without once mentioning how it's different from
>> if/then/else. (I.e., it only works on expressions, not statements. Oh,
>> but wait! Silly me, statements /are/ expressions...)
>
>    ?: cannot contain blocks of code, and both branches much evaluate to
> the same type. No such limitation for if/then/else.

Quite. The book doesn't bother mentioning any of that.

>> Bizarrely, if you don't specify a return type, it defaults to int. Not,
>> say, void. :-o
>
>    Not in standard C++ (where it's an error).

Oh thank god!

>> Then we learn about global variables. Apparently if you write a variable
>> outside of any block, it's global. No word on exactly when it's
>> initialised, or precisely what "global" actually means. For example, I'm
>> /guessing/ the variable is only in-scope /below/ the line where it's
>> defined. That's how functions work, after all.
>
>    If you define a variable (or function) in the global namespace, it will
> be visible in the entire program. (Yes, you can access it from a different
> compilation unit. You just need to declare it with "extern" in that other
> compilation unit to do that.)
>
>    The problem with global variables is, obviously, name clashes. You'll
> start getting weird linker errors about duplicate names if you make a habit
> of using lots of globals (and then happen to use the same name in two
> compilation units).

 From what I'm seeing, just having multiple compilation units is a 
nightmare. (That's one of the reasons I'm reading this book. I'm hoping 
it's going to explain how to do this stuff properly.)

>    (Also, from a design point of view, global variables decrease abstraction,
> which is bad.)

 From a design point of view, global variables are a terrible idea. But 
that the book bothers to explain why.


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.