[HN Gopher] Teaching C (2016)
___________________________________________________________________
Teaching C (2016)
Author : arkj
Score : 139 points
Date : 2022-09-11 11:47 UTC (11 hours ago)
(HTM) web link (blog.regehr.org)
(TXT) w3m dump (blog.regehr.org)
| jvanderbot wrote:
| We're 4 years away from the time when TFA predicts no new
| projects will begin with C.
|
| I wonder how the claim holds up? Certainly not well in the
| embedded space, and Rust mainline kernel development seems still
| a few years away at least.
|
| I'd argue there's some transition in space fsw to c++, but that's
| not really significantly different than C+classes, since most c++
| features and std:: are not allowed.
|
| When does automotive, iot, and other spaces anticipate
| tansitioning?
| elteto wrote:
| FWIW I've seen space FSW instances where both std:: was allowed
| and forbidden. One instance was soft real-time FSW running on a
| customized Linux. Most (sane) C++ was allowed, exceptions were
| not disabled, just disallowed, std:: was allowed during
| initialization, but not past that, memory allocation was only
| allowed during initialization as well, although a stray
| allocation at runtime was only fatal in testing, not during
| flight. It was logged in both cases and considered a critical
| issue. PR reviews had strict checklist rules regarding allowed
| syntax/features. It was very productive using all of the
| necessary C++ features, within reason, to write code.
| pjmlp wrote:
| Automotive standards like AUTOSAR have been using C++ for quite
| some time and now are looking into Rust as well.
|
| https://www.autosar.org/news-events/details/autosar-investig...
|
| Note that MISRA is also adopting AUTOSAR on their standards.
| macintux wrote:
| To be fair to the author, the claim is that it's _at least_ a
| decade away.
| svnpenn wrote:
| > We're 4 years away from the time when TFA predicts no new
| projects will begin with C.
|
| True, but AFT gives us at least 8 years.
| arinlen wrote:
| > _We 're 4 years away from the time when TFA predicts no new
| projects will begin with C._
|
| I'm not sure if this is representative, but most of my recent
| FLOSS projects have all been C89 libraries.
|
| The rationale is that it's trivial to add C bindings in any
| language, it's extremely fast to build, and it runs everywhere.
| andrewmcwatters wrote:
| This is the exact reason I build and ship using C89.
| chrchang523 wrote:
| In your case, how much compatibility is lost from using C99
| over C89? (I'm comfortable with C99 and still write some low-
| level multiplatform code in it, but losing the ability to
| declare variables where they're first used is a bridge too
| far for me...)
| SubjectToChange wrote:
| Just for reference, projects like SQLite use C99.
|
| IMO, targeting C89 is only warranted when you know for a
| fact it's needed. After all, not only is C99 a good
| improvement but toolchains stuck on C89 are not the type of
| toolchain I'd want to support.
| arinlen wrote:
| > _In your case, how much compatibility is lost from using
| C99 over C89?_
|
| Until somewhat recently C89 was the latest version of C
| that was supported by the MSVC compiler. Support for C99
| was always terribly broken and Microsoft chose to claim it
| did supported C99 but without supporting mandatory
| features, which meant they did not in fact supported C99.
|
| This sad state of affairs only changed significantly in
| 2020, with a lowkey announcement.
|
| https://devblogs.microsoft.com/cppblog/c11-and-c17-standard
| -...
| bowsamic wrote:
| I have nothing to say other than that I love C and I will always
| love C. That love affair began when I first walked through the
| tutorial chapter of K&R, and it never died down. I'm not sure
| what it is, but it is just beautiful to me.
| projektfu wrote:
| How strange, I was going to respond to a question about this
| code:
|
| https://git.musl-libc.org/cgit/musl/tree/src/string/memchr.c
|
| and the user has completely disappeared along with their
| comment/question.
|
| Anyhow, you can think about the __GNUC__ part as an attempt to
| fast-forward the loop by testing size_t-length chunks for the
| character by XOR-ing the chunk with a repeated string of that
| character. The first loop aligns the pointer for the fast-
| forward. The final loop is then used to test the unaligned part,
| which when not using __GNUC__, would be the complete loop.
|
| I felt the need to answer because I'd done the work.
| DrNosferatu wrote:
| What about the Deitel books?
| hnthrowaway0315 wrote:
| Just curious, is there a C system programming book that gradually
| feeds the readers with progressive (in difficulty) sys
| programming projects? I red CSAPP and that is a good one, but the
| scope of the projects is a bit limited.
| rramadass wrote:
| You may find _UNIX Systems Programming: Communication,
| Concurrency and Threads by Kay Robbins & Steven Robbins_
| useful.
| enahs-sf wrote:
| As I think about teaching my son programming, I think I would
| start with C and assembly because although it's super low level,
| it gives you a fundamental understanding of how the machine
| works. The debugging and problem solving skills these languages
| impart will also be invaluable.
| SubjectToChange wrote:
| >... it gives you a fundamental understanding of how the
| machine works.
|
| ISO/GNU C is unfit for programming classes of devices as
| ubiquitous as smartphones, or virtually any type of SoC. There
| is a reason CUDA/OpenCL/ROCm/SYCL exist and why they can't be
| programmed like usual C if you want performance.
| mannykannot wrote:
| "The other way of teaching undefined behavior, by looking at its
| consequences, is something that we should spend a bit of time on,
| but it requires a different kind of thinking and we probably
| won't expect the majority of students to pick up on all the
| subtleties -- _even seasoned professional C programmers are often
| unaware of these._ "
|
| I feel that last phrase exemplifies why this should be given
| quite a lot of attention. It is also the sort of thing that will
| lead a student to a deeper insight into the language and how it
| differs from the other procedural languages that they are likely
| to already be familiar with (the same can be said for memory
| management, BTW.)
|
| Such a course might be something of a grind, but if so, it would
| inculcate the right sort of attitude for programming competently
| in C!
|
| For dessert, take a quick look at some Obfuscated C winners.
| blinkingled wrote:
| RMS recently released reference manual for GNU C - I am finding
| it to be direct and succinct.
|
| Edit: I used to teach C to a group of undergrads and one question
| that came up often was around the special significance of the
| main function and order of definition of functions.
|
| The RMS book addresses this very succinctly -
| Every C program is started by running the function named main.
| Therefore, the example program defines a function named main to
| provide a way to start it. Whatever that function does is what
| the program does. The main function is the first one called when
| the program runs, but it doesn't come first in the example code.
| The order of the function definitions in the source code makes no
| difference to the program's meaning.
|
| https://lists.gnu.org/archive/html/info-gnu/2022-09/msg00005...
| If you understand basic concepts of programming but know nothing
| about C, you can read this manual sequentially from the beginning
| to learn the C language.
| curious16 wrote:
| Can anyone link me to the pdf directly. I don't find it on the
| link above. I am stupid.
| treeblah wrote:
| There's no direct PDF, you have to build it yourself w/ TeX
| by cloning the repo: git clone
| https://git.savannah.gnu.org/git/c-intro-and-ref.git cd
| c-intro-and-ref/ make c.pdf
| 1vuio0pswjnm7 wrote:
| I am stupid, too. I generally do not use git(1). I wrote a
| short script to download the manual as a single 639K text
| file. I do not use a GUI or mouse so this makes it easier for
| me to work with code snippets. I also reformat the text to
| match personal preferences. Here is an example script using
| popular curl program to make the HTTP requests.
| # requirements: curl, links, perl, texinfo (Linux), texi2html
| (BSD) #!/bin/sh set -v;
| x0=c-intro-and-ref.git;
| x1=https://git.savannah.nongnu.org/cgit/; test -d
| $x0||mkdir $x0;cd $x0||exit; for x2 in Makefile
| c.texi cpp.texi fdl.texi fp.texi texinfo.tex;do echo
| url=$x1$x0/plain/$x2; echo output=$x2; echo
| user-agent=\"\"; done|curl -K/dev/stdin -s;
| case $(uname) in :) ;;*BSD) texi2html --no-headers
| --no-split --html c.texi ;;Linux) makeinfo --no-
| headers --no-split --html c.texi esac; #
| personal preference for ~15-inch screen: 4 space indent,
| 60-70 max chars per line links -width 70 -dump .html
| \ |sed '/^ *Link:/d;/^ *\*/s/\*//;s/^/ /;/Jump to:
| /{N;N;d;}' > c.txt; exec less c.txt;
| 6581 wrote:
| There is no PDF.
| veqq wrote:
| There is no pdf. Following the chain, you get to a git you
| can download. But this guy has a tar of it as a single html
| page.
|
| https://forums.linuxmint.com/viewtopic.php?t=381284
| Snarwin wrote:
| Someone has uploaded a PDF to github, here:
|
| https://github.com/VernonGrant/gnu-c-language-manual
| xphos wrote:
| You know I can think of a handful of examples where main is not
| true. C to my understanding does not define that the
| implementation does and think this is kind of exactly what the
| other is saying that this implied assumptions lead to issues in
| C development. This albeit is an extremely superficial
| assumption that isn't in 99% of cases going to matter except in
| of course security and embedded systems
|
| I think the biggest issue with C is that it's taught as the
| programs you are building is foundation of everything while
| brushing under the rug that in also all course work you are not
| build C on bare metal you almost always are building on on OS
| which runs an implemented hardware which are extremely
| important. But by teaching your building on this all powerful
| language makes overconfident programmers. I've known so many
| developers who jump the gun and think they are write what will
| happen on the computer without understanding how high in the
| clouds they normally are.
| jalino23 wrote:
| thank you for this!
| WalterBright wrote:
| > The order of the function definitions in the source code
| makes no difference to the program's meaning.
|
| Not exactly true. Consider: #include
| <stdio.h> int foo(double d) { return (int)d; }
| int main() { printf("%d\n", foo(3)); return 0; } /*int
| foo(double d) { return (int)d; }*/
|
| This prints different results depending on whether `foo` is
| defined before `main` or after `main`. This is caused by
| implicit function declaration.
|
| gcc will warn about this if the -std=c11 switch is thrown, but
| by default it will compile without error or warning.
| stephencanon wrote:
| Strictly speaking he's correct as "definition" is distinct
| from "declaration", but yeah.
| WalterBright wrote:
| I wrote definitions in the example, and the order
| dependence is clear.
| kragen wrote:
| But if you _declare_ the foo function before main, it
| works correctly regardless of where it 's _defined_. The
| definition just has the effect of also declaring it,
| which is what makes the difference.
|
| (Of course _you_ know all this much better than I do, but
| someone younger reading this thread might be mystified.)
| WalterBright wrote:
| That wasn't the statement in the book, though. The thing
| is, this is a serious misfeature which isn't present in
| other languages, and can cause bizarre problems to the
| poor newbie user.
|
| This order dependency is why C source code tends to be
| written bottom-up, rather than the more natural top-down.
| blinkingled wrote:
| gcc 12.2 on Arch warns about it with no switches - sure RMS
| did not put a disclaimer on his claim but one can reasonably
| assume he meant if you write correct C the order will not
| matter. (Btw I have a feeling every statement about C would
| need to carry that disclaimer lol - main will be called if
| you did not LD_PRELOAD a .so that caused premature exit in
| init function etc.) gcc /tmp/testf.c
| /tmp/testf.c: In function 'main': /tmp/testf.c:4:18:
| warning: implicit declaration of function 'foo' [-Wimplicit-
| function-declaration] 4 | printf("%d\n", foo(3));
| | ^~~
| marcodiego wrote:
| Here gcc (9.4.0) throws a warning if the first declaration is
| commented and the second one uncommented, but it prints "0".
| Care to explain why?
| WalterBright wrote:
| Because foo() gets implicitly declared as accepting int
| arguments, when it actually accepts a double. The double
| bits interpreted as an int are 0.
| edflsafoiewq wrote:
| On x64, foo(double) expects its argument in xmm0, but
| foo(int) expects it in rdi. So the 3 passed in rdi is
| ignored and it operates on whatever happened to be in
| xmm0.
| WalterBright wrote:
| Yes, you're right. Thanks for the correction. I was
| thinking of the Windows C ABI.
| WalterBright wrote:
| Amusingly, the ImportC compiler I wrote will produce the same
| result regardless of the order, because it allows forward
| references.
| synergy20 wrote:
| Would be nicer if RMS can add TOC on the PDF, to make
| navigation _much_ easier.
| [deleted]
| CJefferson wrote:
| Having taught C at University, I found the hardest bit being how
| many "well, but..."s to give.
|
| C feels like a very simple language, but there are lots of subtle
| corners which probably don't need teaching at first.
|
| On the other hand, I think it's important to hammer home
| "undefined behaviour" early. There are too many guides that say
| writing outside the bounds of an array "writes to memory outside
| the array", which simply isn't true. It might write, it might
| not, who knows, undefined behaviour means all bets are off.
|
| In general I feel a lot of practical teaching of C is teaching
| about undefined behaviour, which is something many other
| languages (Java, Python, Haskell, Rust), either don't have, or
| where they do beginners won't stumble across it.
| bitwize wrote:
| It's high time we declare C "unsafe at any speed" and cease
| teaching it to every student. Only those who really need it
| (legacy C codebase, microcontroller with a toolchain that doesn't
| yet support Rust) need to learn it.
| wudangmonk wrote:
| I completely agree. Rust exists already so I do not understand
| why all the other languages need to continue existing. Only
| those that use Rust can be considered to be a good person since
| using Rust is the morally responsible thing to do.
|
| The question then becomes, why do we want more evil people in
| the world?. Does that make any sense? because that's exactly
| what you get when you don't use Rust.
| zbird wrote:
| Rust doesn't even have a formal specification at this time.
| Technically speaking, everything in Rust is undefined
| behaviour. That's a hard sell for, e.g., people writing
| safety-critical systems.
|
| Another problem recently was that compiling Rust required
| downloading a binary blob from Mozilla. That's a no-go for
| many projects.
| pjmlp wrote:
| AUTOSAR is looking into it, while Ada Core is collaborating
| with Ferrous Systems to bring Rust to the kind of clients
| that usually use Ada.
|
| Meanwhile Microsoft has finally acknowledged picking C for
| Azure Sphere was a bad idea for its overall security story,
| and is now adding Rust support.
| Kamq wrote:
| C is unsafe. That's kind of the point of it.
|
| But just because it's unsafe doesn't mean it should never be
| used.
| pjmlp wrote:
| Its use should be considered to the same extent as a macro
| assembler.
| lionkor wrote:
| How do you tell apart a student that will later work on a
| legacy C codebase from one that won't?
| absolut-dolt wrote:
| Imagine being this drunk on the kool-aid.
|
| Just telling on yourself, "I can't write software without
| training wheels", "I couldn't be bothered to learn how pointers
| work", so flagrantly.
|
| Rust is unspecified, lacks real battle testing, and lacks any
| substantial track record.
|
| Comparisons to C are comical, and discussing Rust as being a C
| replacement as if it were a forgone conclusion is just... I
| mean I can't think of any way to phrase this that won't result
| in a ban - so use your imagination.
|
| Rust is probably a fine language. A lot of y'all down the
| rabbit hole need a reality check though.
| pjmlp wrote:
| Powering VSCode search engine, AWS Fargate infrastructure,
| ChromeOS and Android hypervisor infrastructure, Azure IoT,
| Firefox rendering engine, Android Bluetooth stack ....
| shadowofneptune wrote:
| _C Programming: A Modern Approach_ was my first introduction to
| programming outside of writing a few python scripts (didn 't know
| I could define my own functions, for example). With just it and
| MVSC I was able to pick up a lot of the general concepts and
| practices, Last project I made while studying the book was a
| clock for decimal time and French Republican dates in ncurses.
| This was only back in 2020, so it still is relevant.
| commandersaki wrote:
| Also worth teaching: -fno-strict-aliasing.
| einpoklum wrote:
| I disagree. That is, when teaching C, I never gave examples
| avoiding any aliasing, and if it somehow came up, I advised
| against it. But I don't think it's a good idea to invest
| teaching time in compiler options regarding aliasing; it's too
| specific for an introductory C course.
| synergy20 wrote:
| fully agree, use strict-aliasing only after profiling and on
| your bottleneck code, if necessary, otherwise, just use no-
| strict-aliasing(linux kernel uses it too)
| astrange wrote:
| `-fno-strict-aliasing` is even less formally defined than C
| itself is, so I don't think it's a good tool, you're just
| hoping it works for your program and not actually checking.
| UBSan/ASan cleanliness is a better goal.
| lifthrasiir wrote:
| There is a comment mentioning this. I do have a somewhat
| different view that you should minimize the number of
| "reinterpreting" casts (stealing the C++ terminology) in
| general, which is often ill-advised at the first place. This
| practice frequently eliminates the need for -fno-strict-
| aliasing.
| macintux wrote:
| Not only an insightful post, but also a fair number of
| interesting comments.
|
| A couple of resources I found in the comments:
|
| * A short list of safety rules for C:
| https://en.wikipedia.org/wiki/The_Power_of_10:_Rules_for_Dev...
|
| * A much longer document, 42 rules for coding in C and C++:
| https://pvs-studio.com/en/blog/posts/cpp/0391/
|
| Update: also, a 210-comment thread from 2018:
| https://news.ycombinator.com/item?id=18334476
| bluetomcat wrote:
| C should be taught like any other language. One should understand
| the historical context in which a language was born and why it
| gained popularity. A lot of "vintage" C code is indeed bad
| because elementary software engineering principles were not
| widely understood back then. Pascal code of the same vintage
| isn't significantly better, either. We've walked a way in
| collectively understanding the importance of modularity, cohesion
| and coupling and balancing complexity, and that smart isn't
| always better in the long run.
| qsort wrote:
| I slightly disagree.
|
| C still is, and will continue to be for the foreseeable future,
| the lingua franca, the least common denominator. Acknowledging
| how C comes with a very... interesting set of tradeoffs that
| make it uniquely well-suited for certain purposes and at the
| same time incredibly dangerous is a worthwhile proposition if
| one is aiming to truly understand C development.
| fallat wrote:
| I think you meant "lowest common denominator" or "most common
| denominator"...
| qsort wrote:
| Wikipedia has both forms:
| https://en.wikipedia.org/wiki/Lowest_common_denominator
|
| I'm not a native speaker - this is a genuine question -
| does it sound weird to say "least common denominator"?
| bluetomcat wrote:
| True, but a good C course should explain exactly those
| concepts and what kind of problems (in relation to assembly
| and other HLLs) was C meant to solve back at the time.
|
| I would highlight the following:
|
| * Structured programming support, which means nested loops
| and conditionals without a primary need for "goto" jumps,
| enabling a sense of "depth" that is missing in the "flat"
| world of assembly
|
| * Expression-oriented syntax, meaning that operators (even
| those having a side-effect) return a value of a certain type,
| and can be nested, again enabling recursive program structure
| versus a flattened one
|
| * Global symbol allocation and resolution, which means that a
| programmer uses names rather than addresses to refer to
| global variables and functions
|
| * Abstraction over function calling conventions, which
| enables the programmer not to worry about function prologues
| and epilogues and the order of pushing arguments on the stack
| or in registers
|
| * Automatic storage management, meaning that a function-scope
| local variable is used by the programmer with its name and
| the compiler decides whether to put it in a register or at a
| certain offset in the stack frame
|
| * Rudimentary integer-based type system that has the
| distinction between a scalar and a fixed-size collection of
| scalars laid-out sequentially (arrays), and special integers
| called "pointers", supporting a different set of operations
| (dereferencing to a certain type and adding or subtracting
| other integers from them, without any safety guarantees
| whatsoever)
|
| Nothing more, nothing less. Not understanding these
| foundations is the source of major pain.
| shadowofneptune wrote:
| The expression-ness of C really sets it apart from even its
| successors. Declarations look like expressions, everything
| does. You can see in C code from the time how heavily
| expressions are used. C++, Java, etc. all added a bunch of
| new keywords to the syntax that make it much more like
| Pascal or other 'normal' languages. The culture of those
| languages leans much more towards statements as well.
| pjmlp wrote:
| Macro Assemblers, which were never a thing in UNIX, do
| offer support for structured programming, see MASM, TASM,
| or going back to the days C was born, something like HLASM
| on IBM mainframes.
|
| Additionally many of the C features had already been sorted
| out in JOVIAL, NEWP, PL/I, BLISS among others about a
| decade before C was born.
|
| C was solving the issues of UNIX v3 design, that is all.
|
| Plenty of languages can be used to teach low level
| programming concepts.
| SubjectToChange wrote:
| > C still is, and will continue to be for the foreseeable
| future, the lingua franca, the least common denominator.
|
| In the context of platform ABIs, sure. The widespread
| stabilization and ossification of C ABIs is a boon for the
| rest of the ecosystem but it's entirely at the expense of the
| C language/stdlib. Hence the performance advantage of
| projects like fmtlib.
|
| Notwithstanding its ubiquity C is in many ways "The Sick Man
| of Asia". Every major C compiler is written in C++ with
| tooling heading the same way. The dominance of C++ in the
| heterogeneous space has accelerated this trend and spread it
| to many HPC libraries. Even foundational bits such as
| Microsoft's UCRT or llvm-libc are written in C++.
|
| On the current trajectory C will become the next Fortran,
| i.e. a widely used language which is nonetheless unable to
| support itself.
| whateveracct wrote:
| I learned C mostly on pen-and-paper exercises at my university.
| Lots of drawing the stack and heap.
| unwind wrote:
| That is ... a bit weird, since C does not assume, recommend or
| require that non-heap variables are implemented using a stack.
|
| It's weird to teach a language while also ripping a hole in one
| of its main abstractions and assuming stuff about how that
| works, in my opinion.
| turtledragonfly wrote:
| Genuinely curious: do you know of any C implementations that
| do not use a stack for such cases?
|
| It seems so prevalent that locally-scoped variables are often
| referred to as "stack variables" in casual conversation, but
| I'm curious of cases where it's not true...
| tamsaraas wrote:
| C is an achievement that must be unlocked by programming in
| different other high-level languages for years. Without this - C
| will be pointless lecture.
| [deleted]
___________________________________________________________________
(page generated 2022-09-11 23:00 UTC)