Advanced C

I

Ingo Menger

Flash said:
Ingo Menger wrote:

You said written in C, it isn't it written in C + other things.

If it is written in C and asm, then the statement "it is written in C"
is obviously true.
Not so for "It is entirely written in C", "It is written in C and only
C", "It is written in C and nothing else", none of which I did state.
You might, I would say it is mostly written in C since I recognise that
it is not written in C in its entirety.

The same is true for the GC.
Some requires assembler, some can be done with extensions to C, but
neither assembler not those extensions are actually part of C. If you
think they are, then point them out in a normative section of the standard.

I don't think so, and I wonder how you might think that I'd think so.
 
M

Michael Mair

rainbve said:
pemo said:
What would expect to be covered?

Say you'd already attended a course, that had covered stuff like structs,
pointers, bitwise and logical operators, multi-demensional arrays [and
the like], *but* hadn't covered other stuff like recursion, unions,
bit-fields [and the like].

What topics would /should be covered on a course that takes students
further?

Depends on what the students should be able to do after the
course. Here is a (roughly translated) table of contents for a
course I taught last year; <snip> indicates left-out parts.
Note that the topics are not necessarily mentioned the first time
when they appear in the ToC:

,----
0 Intro

II Kür
7 File I/O
<snip>
8 Tools
8.1 gcc
8.2 make
8.3 lint/splint
8.4 ar
8.5 cvs
8.6 gdb and ddd
8.7 electric fence
8.8 prof/gprof
8.9 Editor
8.10 Overview
9 Optimisation

<snip>

What are the subjects in 8.4 and 8.7?

These are actually off-topic round here, as you probably
already inferred from the "Tools" heading...
<OT>
I taught in a unixoid environment.

ar is a program to create and change archives as well as
extract from them; in my experience and in the above mentioned
section especially, it is used to create libraries from object
files. For more details
man ar
(you can also try this with google)

electric fence is a debug library you can link with; it replaces
malloc()/calloc()/realloc()/free() and detects access to a memory
location after (or, if wished, before) the allocated memory you
own or, by option, access to memory which once belonged to you
but has been freed.
It is an old and simple tool and quite easy to use and usually
is a quick help for finding subtle off-by-one errors.
There are better tools but I was not aiming at making the
students into professional programmers but give them a good
overview over _possible_ tools -- I often had (and sometimes still
have) the revelation "oh, such a tool exists? My, how much time this
could have saved me when..."
</OT>

Cheers
Michael
 
M

Michael Mair

Imre said:
Do you think it is not enough?

8 A bit-field shall have a type that is a qualified or unqualified
version of _Bool, signed int, or unsigned int. A bit-field is
interpreted as a signed or unsigned integer type consisting of the
specified number of bits.93) If the value 0 or 1 is stored into a
nonzerowidth bit-field of type _Bool, the value of the bit-field
shall compare equal to the value stored.




Could you explain this?

Read the threads
- containing <[email protected]> which refers to
- the one starting at
<[email protected]>
(longish but enlightening)
- and maybe the one starting at
<[email protected]>

Cheers
Michael
 
K

Keith Thompson

Ingo Menger said:
If it is written in C and asm, then the statement "it is written in C"
is obviously true.
Not so for "It is entirely written in C", "It is written in C and only
C", "It is written in C and nothing else", none of which I did state.

I interpret the statement "It is written in C" as equivalent to "It is
entirely written in C", though the latter is more explicit.

Since this has become a debate about the meanings of English sentences
rather than about the C programming language, I suggest we leave it at
that.
 
B

Ben Pfaff

Skarmander said:
Ben said:
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x1f6},*p=
b,x,i=24;for(;p+=!*p;*p/=4)switch(x=*p&3)case 0:{return 0;for(p--;i--;i--)case
2:{i++;if(1)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}

This code invokes undefined behavior by accessing b[7]. Here's a
possible fix:

char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x11f6},*p
,i=24;for(p=b;p+=!*p;*p/=4)switch(*p&3)case 0:{return 0;for(p--;i--;i--)case 2
:{i++;if(1)break;else default:continue;if(0)case 1:putchar(a[i&017]);break;}}}

Excellent spotting. I've been posting that sig for years and no
one's ever noticed before. Certainly I hadn't.

Your fix is fine, of course. Here is a different one that
introduces a small amount of additional misdirection:

char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x11f6},*p
=b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}
 
F

Flash Gordon

Keith said:
I interpret the statement "It is written in C" as equivalent to "It is
entirely written in C", though the latter is more explicit.

As do I. After all a C programmer could be expected to follow something
written in C but if critical bits are not C then a C programmer might
not stand a chance.
Since this has become a debate about the meanings of English sentences
rather than about the C programming language, I suggest we leave it at
that.

Indeed. I'll drop it here.
 
T

Tim Rentsch

Ben Pfaff said:
Bit-fields have the same type as another C language type, such as
signed int or unsigned int. I don't see how they would help with
24-bit signed arithmetic, at least without involving undefined
behavior.

If the operations being done don't overflow a 24 bit result, then
signed bit-fields should work just fine. Operations that overflow
would produce implementation defined or undefined behavior, but
overflow when using signed operands is undefined behavior in
any case. A 24 bit signed bit-field should behave just as nicely
as a 24 bit signed integer type that's a built in integer type
(as long as you don't want to have a pointer to it, make an
array of them, etc).

Incidentally, bit-fields are declared using int, signed int, or
unsigned int, but the type of a bit-field (usually) isn't quite
the same as the type used in the declaration but without the
bit-field-ness. Consider:

struct { unsigned u; unsigned b:1; } s = { 1, 1 };

if( (s.u << 31) > 0 ) printf( "foo" );
if( (s.b << 31) > 0 ) printf( "bas" );
printf( "\n" );

The bit-field s.b is an unsigned type, and it's legal to assign
any integral value to it. But it isn't the same as 'unsigned',
as the code fragment above demonstrates.
 
B

Ben Pfaff

Tim Rentsch said:
If the operations being done don't overflow a 24 bit result, then
signed bit-fields should work just fine. Operations that overflow
would produce implementation defined or undefined behavior, but
overflow when using signed operands is undefined behavior in
any case.

But what is the benefit of a 24-bit signed integer bit-field over
a wider non-bit-field type, for the purpose of making
calculations with 24-bit signed integers? Imre seems to be
saying that there is some advantage, but I don't see it.
A 24 bit signed bit-field should behave just as nicely as a 24
bit signed integer type that's a built in integer type (as long
as you don't want to have a pointer to it, make an array of
them, etc).

Pretty big caveats, in my opinion.
struct { unsigned u; unsigned b:1; } s = { 1, 1 };

if( (s.u << 31) > 0 ) printf( "foo" );
if( (s.b << 31) > 0 ) printf( "bas" );
printf( "\n" );

It took me a minute to understand what was going on there. Thank
you for the enlightening example.
 
T

Tim Rentsch

Ben Pfaff said:
But what is the benefit of a 24-bit signed integer bit-field over
a wider non-bit-field type, for the purpose of making
calculations with 24-bit signed integers? Imre seems to be
saying that there is some advantage, but I don't see it.

Of course I can only speculate about what he was thinking, but here's
my guess. He's working on a platform (or platforms) that use two's
complement and where the implementation defines conversion to a signed
integer type to take just the low order bits (ie, when the value is
out of range). Now his 24-bit type will wrap around the way most
two's complement machines actually do. The advantage is he can use
normal assignment, etc, and not have to write '&0xFFFFFF' all over
the place. Maybe that isn't much of an advantage, but it's something.

Pretty big caveats, in my opinion.

It's noticeable, for sure. With a syntactic inconvenience these
limitations can be gotten around, eg,

typedef struct { signed v:24; } int_24;

int_24 things[20];

for( i = 0; i < 20; i++ ) things.v = 0;

Using .v or ->v is less onerous than doing explicit masking. More
important, the knowledge that elements of 'things' hold a 24-bit
datatype is localized rather than having to be repeated throughout the
code.

It took me a minute to understand what was going on there. Thank
you for the enlightening example.

You're welcome. I wasn't meaning to be cryptic, although the point is
a bit understated. If the shift amount were changed from 31 to 15
this code fragment might make a good C interview/test question.
 

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

Forum statistics

Threads
473,733
Messages
2,569,439
Members
44,829
Latest member
PIXThurman

Latest Threads

Top