Additional resources to understand C better.

I

Indian.croesus

Hi,
I apologise if this is not the forum for my question.

I am a starter in C and I have come to a point where I can not figure
out if knowledge of assembly language is really essential for an in
depth understanding of C. Also while going through some of the old
posts, essentially as an exercise to understand C better, I read the
following from one Mr. Keith.

"One concrete example is the C implementation on Cray vector machines.
A machine-level address is a 64-bit quantity that points to a 64-bit
machine word, but the C compiler has CHAR_BIT==8, so it needs a
mechanism to point to 8-bit bytes within words. An int* pointer is a
machine address, but a char* or void* pointer has a 3-bit offset
stored in the otherwise unused high-order bits of a word pointer.
This is implemented entirely in code generated by the compiler, not in
hardware. A char* pointer value with a non-zero offset field is a C
address, but it's not a machine address. "

That just flew over the top of my head. :(

What material, books or internet resources, can I read and / or code to
understand that stuff.

The problem with not knowing a thing and trying to learn is that one
does not know how much one does not know. So if you can point me to
additional material or topics that you feel one should know, please do
point me to it.

Thanks in advance.

IC.
 
J

Jack Klein

Hi,
I apologise if this is not the forum for my question.

I am a starter in C and I have come to a point where I can not figure
out if knowledge of assembly language is really essential for an in
depth understanding of C. Also while going through some of the old
posts, essentially as an exercise to understand C better, I read the
following from one Mr. Keith.

"One concrete example is the C implementation on Cray vector machines.
A machine-level address is a 64-bit quantity that points to a 64-bit
machine word, but the C compiler has CHAR_BIT==8, so it needs a
mechanism to point to 8-bit bytes within words. An int* pointer is a
machine address, but a char* or void* pointer has a 3-bit offset
stored in the otherwise unused high-order bits of a word pointer.
This is implemented entirely in code generated by the compiler, not in
hardware. A char* pointer value with a non-zero offset field is a C
address, but it's not a machine address. "

That just flew over the top of my head. :(

What material, books or internet resources, can I read and / or code to
understand that stuff.

The problem with not knowing a thing and trying to learn is that one
does not know how much one does not know. So if you can point me to
additional material or topics that you feel one should know, please do
point me to it.

Thanks in advance.

These are the kind of thing that you _never_ need to worry about
writing applications in standard C.

Some programmers take advantage of the "fact" that certain types have
the same size on the particular implementation they happen to be
familiar code. The write code that unnecessarily makes use of this
equivalence of size, then they are surprised when it breaks when
compiler on a different platform, or maybe even a newer version of the
same compiler.

I assume the quotation was in reply to somebody who asserted that all
pointers, or even all pointers to objects, have the same size. That
is true in most C implementations, but not all.

In the case Keith was talking about, the Cray is a computer that is
built for sheer computation speed, what was then called a
"supercomputer". It was not used for word processing or web browsing,
but was a very, very expensive machine used for intense number
crunching.

To increase speed, it only reads and writes memory in 64-bit words.
Period. All instructions operate on 64-bit integers or 64-bit
floating point values.

But even number crunching programs might need to write their results
to text files that humans can read. To make it easier for programmers
to use plain old ordinary text, the compiler and library implement an
8-bit character type that is not supported by the hardware.

If you want to have 8-bit character types on a computer that can't
address quantities as small as 8 bits, you have two choices.

Choice 1 is to use a whole 64-bit word for each character, storing the
character in the lowest 8 bits and wasting the other 56 bits. But
that can waste a lot of memory.

Choice 2 is to pack up to eight of those 8-bit characters into each
64-bit machine word. But the problem now is how to specify just one
of those characters, when the hardware machine address is the address
of the entire 64-bit word. To do that, you need a field of at least 3
bits somewhere, that can hold eight different values specifying which
of the eight characters in the machine word you want.

So on this platform, a pointer to any of the character types, or a
pointer to void, must have at least three additional bits of
information that a pointer to a 64-bit double, for example, does not
need.
 
G

goose

Hi,
I apologise if this is not the forum for my question.

I am a starter in C and I have come to a point where I can not figure
out if knowledge of assembly language is really essential for an in
depth understanding of C.

Knowledge of assembly language is required for an in depth
understanding of assembly language.

It is possible (possibly not very useful) to have an in-depth knowledge
of C and have absolutely no knowledge of the machine architecture
you are targetting. Some might argue that this is the best way.

The state you should be aiming for is absolute and in depth knowledge
of C, while noting that many different architectures will implement the
same thing differently (which is why learning by experimentation is
not a Good Thing).
Also while going through some of the old
posts, essentially as an exercise to understand C better, I read the
following from one Mr. Keith.

"One concrete example is the C implementation on Cray vector machines.
A machine-level address is a 64-bit quantity that points to a 64-bit
machine word, but the C compiler has CHAR_BIT==8, so it needs a
mechanism to point to 8-bit bytes within words. An int* pointer is a
machine address, but a char* or void* pointer has a 3-bit offset
stored in the otherwise unused high-order bits of a word pointer.
This is implemented entirely in code generated by the compiler, not in
hardware. A char* pointer value with a non-zero offset field is a C
address, but it's not a machine address. "

That just flew over the top of my head. :(

I wouldn't worry about it, if I were you. Mr Thompson and other
regulars
of this group tend to know all the arcane nooks and crannies of the
C language *in addition* to knowing their target (and other)
implementations
thoroughly.

Be careful not to mix up the two though. For example, if you experiment
on your desktop and find that a long is exactly 32 bits wide, you
cannot
assume that a long in C is 32 bits wide always (a 64 bit platform might
decide to have longs of 64 bits width).

What material, books or internet resources, can I read and / or code to
understand that stuff.

Do you *want* to understand that stuff? The reason I ask is because
that stuff will differ from platform to platform.
The problem with not knowing a thing and trying to learn is that one
does not know how much one does not know. So if you can point me to
additional material or topics that you feel one should know, please do
point me to it.

A good start would be the newsgroup for your particular platform.

goose
 
R

Randy Howard

goose wrote
(in article
It is possible (possibly not very useful) to have an in-depth knowledge
of C and have absolutely no knowledge of the machine architecture
you are targetting. Some might argue that this is the best way.

Depends upon what you actually intend to do down the road, but
in general, yes.
The state you should be aiming for is absolute and in depth knowledge
of C, while noting that many different architectures will implement the
same thing differently (which is why learning by experimentation is
not a Good Thing).

It can be. For example, when you experiment with a single code
base on multiple compilers, operating systems and processor
architectures and see how they work the same or differ. It's
"experimenting on a single system/compiler" that's prone to bad
habit forming, imo.
 
I

Indian.croesus

Thanks a lot all of you and thanks Mr. Jack, that really helped a lot.

I am mighty confused. I think I understand C fairly well now and am
comfortable with pointers but I do not know "what next". When I say
that, I mean I am overwhelmed by the fact that I should learn about the
calling conventions, as also concepts like implementing OOPS using C,
or perhaps go through the C standards document, from cover to cover. So
I need a little guidance in that direction. Perhaps I am not able to
frame my question in a coherent manner but I am hoping that atleast
some of you must have felt the same during your intial tryst with C and
your experience can throw some light on how can I take the next step.

Thanks once again.

IC
 
G

goose

Randy said:
goose wrote
(in article


Depends upon what you actually intend to do down the road, but
in general, yes.


It can be. For example, when you experiment with a single code
base on multiple compilers, operating systems and processor
architectures and see how they work the same or differ.

That's equally bad; what if all the ones you manage to get
your hands on implement malloc using pages/blocks/whatever
of 32 bytes?

The learner gets the idea that malloc allocates in 32 byte blocks?
The non-learner, OTOH, is presented with no danger in experimenting
to determine what his implementation is doing in order to conform
to the standard.

Experimentation *while learning C* is a bad idea in general. I've seen
too many students who believe that they "know" the number of bits
in an int or that they "know" what happens when they go past the end of
an array "in the C language" merely because they experimented and
found out how all their implementations handle that particular UB.
It's
"experimenting on a single system/compiler" that's prone to bad
habit forming, imo.

Not only a single system, but many similar systems whose
similarity is not obvious (different compilers for the same platform
may produce the same opcodes for some C code while being
different implementations).

goose,
 
R

Randy Howard

goose wrote
(in article
That's equally bad; what if all the ones you manage to get
your hands on implement malloc using pages/blocks/whatever
of 32 bytes?

A fair point, but certainly not the "what if" I had in mind.
And also not without being informed, basically, that "all the
world is not a VAX" before they get started. Or in more modern
terms, x86. Add in endian issues, character sets, signed
representations, etc. and pick good variety of targets to
experiment on, and I contend it could have quite the opposite
effect, for a suitably talented student. Given the proper
briefing a good selection in platforms, anybody that still comes
out with nothing but a bunch of misinformed assumptions form
that isn't going to make it to the end of the runway anyway.
The learner gets the idea that malloc allocates in 32 byte blocks?

Whoever said that experimentation must occur in isolation from
other methods and teaching, like good instructors, or good text
books and/or tutorials? You're trying to make a point about
your opinion by carrying it to the point of absurdity through
exaggeration. Sure, there are probably some folks that did
/only/ what you describe without any other forms of learning to
help correct any such bad ideas. I think they are vanishingly
rare in the programmer population though. It was certainly more
likely back when there so many fewer options when it came to
learning materials as compared to today.
The non-learner, OTOH, is presented with no danger in experimenting
to determine what his implementation is doing in order to conform
to the standard.

"The non-learner"? The "non-learner" doesn't learn anything at
all. Do you mean the one that doesn't experiment with actual
compilers, systems and architectures? IMO, you have to be
incredibly uninterested in the topic as a whole to never go down
that path, even a little bit, even when first getting past the
few days with the language when it is explained that C lets you
get closer to the bare metal than other HLLs.
Experimentation *while learning C* is a bad idea in general. I've seen
too many students who believe that they "know" the number of bits
in an int or that they "know" what happens when they go past the end of
an array "in the C language" merely because they experimented and
found out how all their implementations handle that particular UB.

And I'll suspect that of those you have seen, very few of them
experiments on a the kind of "variety" I had in mind when I
wrote the above, or in total isolation from other forms of
learning.
 
C

Chris Torek

What material, books or internet resources, can I read and / or code to
understand that stuff.

You do not *need* to know details about various machine architectures
in order to use the C language. If you *want* to learn such things,
though, your best bet may be a college course on hardware architectures.

(It may also help to learn some background electrical-engineering
principles, although even basic EE courses tend to be much more
intensive than required for understanding simple digital logic.
For instance, there is no need to know about Thevenin and Norton
equivalents, much less analyzing AC circuits and transmission lines,
in order to understand the basic workings of a D or J/K type
flip-flop. Those two -- D and J/K -- are the basis for all other
digital circuits. Of course, transmission line theory can help
explain *why* a digital circuit is misbehaving, but that is another
topic entirely. :) )

Language courses (runtime organization of languages, compiler
design, and so on) may also be helpful, and possibly operating
systems courses.

There are a lot of textbooks that would go with these (authored
by folks such as Hennesy and Patterson, Silberschatz and/or Peterson,
and so on). Knuth (all volumes) and Sedgewick are good reference
works as well, although they focus more on algorithms and data
structures.
 
S

Stephen Sprunk

Thanks a lot all of you and thanks Mr. Jack, that really helped a lot.

I am mighty confused. I think I understand C fairly well now and am
comfortable with pointers but I do not know "what next". When I say
that, I mean I am overwhelmed by the fact that I should learn about
the
calling conventions, as also concepts like implementing OOPS using C,
or perhaps go through the C standards document, from cover to cover.
So
I need a little guidance in that direction. Perhaps I am not able to
frame my question in a coherent manner but I am hoping that atleast
some of you must have felt the same during your intial tryst with C
and
your experience can throw some light on how can I take the next step.

The first step is to start working with advanced data structures and
algorithms, such as trees, hash tables, sorts, etc. You also need to
learn how to decide which to use in various cases, and how to
troubleshoot bugs. In fact, learning to use your debugger well is
probably the single most important thing, since that's what you'll spend
most of your time doing when you start writing more complex programs.
Writing new code is a tiny, tiny part of most programmers' lives; the
rest is spent fixing bugs or hacking in the occasional new feature.

Another important step is learning what the Standard guarantees vs. what
your implementation guarantees and/or what what you've found happens to
work while experimenting. There are many things you'll have picked up
assuming they're correct/portable (or not knowing there's a difference);
porting a program from Windows to POSIX or vice versa is an eye-opening
experience to folks who learned on a single platform. You'll find out a
large part of what you "know" is simply wrong.

That's not to say writing unportable code is bad -- but you need to know
when that's what you're doing, and how to account for it, i.e. writing
wrappers so that 90% of the code is portable and all you need to change
when porting is to write a new wrapper. Networking, threads, GUIs,
makefiles, etc. are all good things to learn once you've mastered the
core language -- and learning how incredibly different they are on
various OSes (if they exist at all) will teach you the importance of
knowing what C guarantees vs. what an implementation
provides/guarantees.

After you've gotten past those hurdles, go find an open source project
that intrigues you and simply read the code. Once you understand it
(which, unless it's tiny, will take a while), try adding a new feature.
It doesn't even matter how big it is or if anyone else finds it
useful -- it's the process that you need to learn. Then go look up some
bug reports and try to diagnose/fix one. If you succeed, contribute a
patch.

All that'll keep you busy for months or even years :)

S
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top