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: Warp
Date: 17 Apr 2012 09:40:45
Message: <4f8d72dd@news.povray.org>
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?

> (Incidentally, the table of contents runs to 21 pages. I always feel 
> that if the table of contents /itself/ merits another table of contents, 
> you're doing it wrong.)

  I have sometimes seen the opposite extreme: A doorstopper book with
a laughably small table of contents which isn't very helpful.

> 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.)

> 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. cout is getting one single
integral value. (Basically invariably this value will be calculated by
the compiler at compile time.) Anyways, it's not like it's important.

> 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.

> 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.)

  (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.)

> Now, this I did not know, but: There is a long int, and a short int. And 
> then there's just int. I had always thought these were three different 
> sizes of integer. But it appears that actually, long int is one size, 
> short int is another size, and plain int refers to whichever one the 
> compiler writer chose on a whim. So there's only actually two integer 
> sizes, and plain int means "I don't care".

  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.)

> The book suggests "never use int, always use short int or long int". If 
> the table is to be believed, long int is 32-bits. Christ knows what you 
> do if you want more bits than that...

  "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. 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).

> The book casually mentions something which /seems/ to be claiming that 
> variables are not initialised to anything in particular unless you 
> specifically request this. That's interesting; I didn't know that.

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

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

> 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.

> 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.

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

> 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 (in which case promoting to floating point would be an
enormous waste of resources).

  If you really want promotion to floating point, then you have to cast
explicitly.

> 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.)

> This being C++, some insane wacko 
> thought that having c++ and ++c would be a good idea, and wouldn't be 
> confusing in any way.

  Who gets confused? I don't.

  There's certainly a big difference between eg:

    while(c++ < 10) std::cout << c << "\n";

and

    while(++c < 10) std::cout << c << "\n";

  If you don't want to made the increment "inline" like that, the
alternative is more verbose.

> 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?

> 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.

> 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).

> 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).

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

-- 
                                                          - Warp


Post a reply to this message

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