C Plain C learning school forum?

Hello,

I am looking for learning plain C, real basics. I am programming for learning experience, and learning without educational service, i.e. school.

Any recommendations:
Is there any board or forum which are dedicated to plain C, accepting programming mistakes and tolerating learning-motivated beginners?
 
You can try https://cboard.cprogramming.com/c-programming/ which I remember being pretty good for most things.

However, you can join pretty much any programming forum regardless of C/C++ or even Java. Most developers are pretty understanding if you just want to stick to ANSI C rather than using another language, so long as you an filter through the occasional "You should use [insert trendy new programming language here] instead because it has built-in XML support!"

I would also suggest keeping away from game development forums because even though making games is IMO a great way to learn how to program, hobbyist game developers often make terrible technology choices to implement their games and 90% of them will simply not be able to comprehend the advantages of C from its elegance and simplicity. They would rather opt for "game making kits" like Unity (.NET) and forgo any kind of programming standards and best practices.

But us FreeBSD forum'ers are also a relatively capable bunch, if you have any programming questions (especially involving POSIX things), perhaps ask them here and we will try to answer :)
 
I would also suggest keeping away from game development forums because even though making games is IMO a great way to learn how to program, hobbyist game developers often make terrible technology choices to implement their games and 90% of them will simply not be able to comprehend the advantages of C from its elegance and simplicity. They would rather opt for "game making kits" like Unity (.NET) and forgo any kind of programming standards and best practices.

thank you I will try this forum

.net, java, ... and all the ugly stuffs, including mono, python, perl everywhere,.... this programming planet has been so much bloated to run something of about 100-200 lines in efficient C.

This is why termcap and ncurses will never die, unless pottering and their allies will make nothing of beauty of Unix, including historical X11.
 
I've also picked up C some years ago just for the sake of finally learning a "real" programming language ;)
Today I'm using C mainly for AVR programming/prototyping as a hobby or writing simple tools (those few for which perl isn't suitable...) from time to time at work, so my needs are relatively simple and basic, but I'm confident enough to at least understand the general direction of what's going on in most source files for x86(_64) systems (e.g. programs for or parts of FreeBSD).

As an Intro I can highly recommend the classic "K&R - The C Programming Language (ANSI C)". I've tried to read several "modern" books on C (e.g. "head first"), but one thing I discovered with most modern programming books is: they all tend to constantly drift off into meaningless blather and advance in small steps wrapped in a lot of text.
K&R2 is very compact and condensed, straight to the point yet very accessible and (IMHO) quite nice to read. It brings you up to speed _very_ fast: within ~50 pages you are able to write useful tools. Then you could either stop reading and look up what you need for new/special cases or just read on for another ~100 pages, as within these ~150 sites everything there is to know about the syntax of ANSI C is covered! The remaining 100 pages of the book cover the unix system interface and the complete reference manual. As said: The book gets straight to the point and the authors never beat around the bush and waste your time.

I still have a copy of the book and regularly refer to it and even pick it up from time to time and just read through a few pages...
I also used the draft of the book on learncodethehardway.org as a refresher a few years ago when I got back to C for prototyping Atmel AVR code. Back then it was a work-in-progress version and freely available, but from what I can recall from that early draft, I'd say the finished book is worth the 30$ it's now offered at.
 
Bookmark this URL somewhere: SEI CERT C Coding Standard Try to learn "secure coding" from the beginning.

I would also suggest keeping away from game development forums
Exactly, game and web developers (not all of them) are framework-hopper. Today React, tomorrow phaser.io and so on. You will learn nothing.

Today I'm using C mainly for AVR programming
Although I don't think OP is interested in AVR programming at the moment, but I have to say MCU programming is one of the best way to teach ISA and C. x86 or not, it doesn't matter. I hope OP give it a chance in the future. AVR programming is fun and educational.

learning without educational service, i.e. school.
Educational services are pretty much dead and gone. I'm not against academia, but they need to implement Garbage Collection! It's not just liberal art, STEM is infected with junk too.
 
Bookmark this URL somewhere: SEI CERT C Coding Standard Try to learn "secure coding" from the beginning.

You don't have to be a cryptologist to develop secure program or implement secure code. You just need to pay attention! Some examples:
* Which one is better, and why? printf("X"); or printf("%s", "X");.
* What's the difference between #define FUNC(x) ((x) * (x)) and #define FUNC(x) x * x.
* Why you should NULL a pointer when you free dynamic memory.
* How to obtain the size of a struct: using sizeof or sum of its memebers' sizes?
 
* Which one is better, and why? printf("X"); or printf("%s", "X");
Neither is better in that case unless the string "X" is not placed in a read-only section of memory, in which case you'd be guarding against memory modification that can potentially expose private data. That said, it would be a bit paranoid to write printf("%s%s%s", "Hello, ", name, "!\n"); instead of printf("Hello, %s!\n", name);. However, printf(user_input); is definitely worse than printf("%s", user_input);. The reason why one is better than the other is left as an exercise to the reader.

I'd also add:
* Why are *++ptr and *ptr++ potential sources of bugs, and what makes ++*ptr safe compared to the other two expressions?

Apart from secure coding is the matter of code style. It's important to remember that "comprehensible" and "readable" are not always the same thing. while (*dst++ = *src++); is a lot more readable, but it's more difficult to comprehend when compared to a slightly longer for loop equivalent, and you may not remember what such "clever" code does if/when you come back to it later.

There are all sorts of styles like style(9) in FreeBSD, Linux, Google, and GNU. You can search for coding style on your favorite search engine to find many of the popular ones. Also, a wide variety of opinions exist regarding all sorts of topics, which may not even be specific to C/C++; one example is limiting line length to 72 screen columns, which is absurd if using(long_variable_names) and qualified.names() in languages_like("Python"):

Tools exist to automatically format your C code. indent(1), or the GNU equivalent gindent(1) (devel/gindent), are the classic go-to solution. More modern options that may work better include clang-format (available with ports like devel/llvm10 if you don't already have the program installed) and Artistic Style (devel/astyle). Use whatever works for you or manually format your code however you want (e.g. you might follow style(9), even if you're not doing FreeBSD-related coding).
 
* Why you should NULL a pointer when you free dynamic memory.
I've read pros and cons of this, and frankly, I'm a decided anti-NULL. I know you're probably following a "convention" that seems to have permeated the "better programming in C" group of programmers. This is no slight on you. I will give you my reasons:

Why?

It's dubious and it's lazy. It attempts to hide bad code.

How?

Because a lot (and I mean a lot) of code I see has multiple references to the same space, eg.

C:
char *ptr = malloc(100);
char *p;

p = ptr;
free(p);
*p = NULL;
/* Sometime later, in code far-far-away: Oops forgot to free ptr */

free(ptr);

/* Yikes */
(It's a simplistic example, but holds that assigned p to NULL afterwards achieves nothing but a warm feeling ) It just doesn't stop double dereferencing.


It might, just might have benefits for when your program eventually segfaults and says it's a NULL but then if you're program is littered with them, good luck finding it.

Also, placing stuff like a local variable:
Code:
*ptr = NULL;
into a function is just a waste of typing as it's destroyed anyway. Too much typing is bad in C, it's why we use "int" for integer and "char" for character and why we absolutely, positively hate those verbose C abominations like C++ and Objective-C... :eek:;)
 
Hello,

I am looking for learning plain C, real basics. I am programming for learning experience, and learning without educational service, i.e. school.

Any recommendations:
Is there any board or forum which are dedicated to plain C, accepting programming mistakes and tolerating learning-motivated beginners?
Get a copy of K&R, read it and particularly make sure that you understand pointers.

If you want to be a bit less stuck in the mud, get a copy of Harbison and Steele as well.
 
  • Thanks
Reactions: a6h
into a function is just a waste of typing as it's destroyed anyway. Too much typing is bad in C, it's why we use "int" for integer and "char" for character and why we absolutely, positively hate those verbose C abominations like C++ and Objective-C... :eek:;)
I'm not too sure what you mean by verbose. Big headers, larger object files maybe. C++ is generally much shorter than C, for instance an example from Rosetta Code.
 
Because a lot (and I mean a lot) of code I see has multiple references to the same space, eg.
Agreed. I see a lot of examples of this and for simple ones, it seems to make sense but for larger codebases if you then factor in that this pointer could be dangling almost everywhere else in the program, it seems a little bit ineffective to just set the local one to NULL. Especially since that will be inaccessible when the function ends anyway.

I got a little bit obsessed with this issue not too long ago and developed this: https://github.com/osen/stent

It basically provides a weak_ptr<T> for C (during debug mode only) so is effectively zero overhead and can detect all use after frees. As a bonus it also provides a typesafe vector<T> to avoid memory issues there. These days I actually find it safer than C++ and the potential that 'this' can dangle with smart pointers.
 
I don't think it had to do with typing as much as they were trying to save space?
It was specifically the typing. C was developed (as was Unix) on an extremely difficult to type on teletype terminal. They wanted to do as little typing possible. That said, some of the shortening was unhelpful. Ken Thompson has said that were he able to do it all over again, he'd spell creat() with an 'e'.
 
Ken Thompson has said that were he able to do it all over again, he'd spell creat() with an 'e'.
Interestingly enough, we now have functions like openat(2) and unlinkat(2). Had creat(2) not been made obsolete by the O_CREAT flag when opening a file, we might have gotten a creatat() function, which seems like a terrible idea.

Of course, had there been an 'e', it would be createat(), which has the English word eat in it twice; it would be a good reminder for me not to skip lunch!
 
I think it was lucky that system include files had short names. Otherwise C compilers on DOS would have been tricky.

So even though UNIX could have longer file names, they decided to show restraint. (Something that I wish current open-source developers would also do)
 
Because a lot (and I mean a lot) of code I see has multiple references to the same space, eg.

C:
char *ptr = malloc(100);
char *p;
p = ptr;
That last line of code is where the bug is. Never ever do that. And if you have to do it, then warn the reader = coder that things are not what they seem to be. The correct variable name is not "p", but "char *local_copy_of_ptr_do_not_modify_this_or_you_will_die = ptr". OK, maybe I'm exaggerating the variable name a little bit.

One thing people need to understand: Pointers are not data. Integers, floats, strings, and things derived or aggregated from those are data. Pointers are metadata: something that describes the real data. And metadata is dangerous. So dangerous that you have to be careful with it. One particularly important aspect of being careful is to not duplicate it. An old colleague of mine had a saying for this: "The man with two watches never knows what time it is". The moment you copy a pointer to a second variable, the probability of the program being broken goes up exponentially.

This is one of the reasons why I always suggest programming languages in which pointers become invisible to users. Doing memory management and tracking of which variable is store where is hard, tedious, and error-prone. It ought to be automated. We should have computers to help us do that, so we don't have to handle it ourselves. C's pointer type is what another old colleague refers to as a "foot-shaped gun": A tool that most of the time hurts you.
 
That last line of code is where the bug is. Never ever do that. And if you have to do it, then warn the reader = coder that things are not what they seem to be. The correct variable name is not "p", but "char (local_copy_of_ptr_do_not_modify_this_or_you_will_die = ptr". OK, maybe I'm exaggerating the variable name a little bit.
The problem is you do this implicitly every time you call a function that takes a pointer as an argument. This game of hot potato with dynamically-allocated memory reminds me of the classic sketch:

Me: Who frees this memory?
C: Yes
Me: No, I mean who is responsible for freeing this memory?
C: Yes, he is
 
I'm not too sure what you mean by verbose. Big headers, larger object files maybe. C++ is generally much shorter than C, for instance an example from Rosetta Code.
Right so the C++ example is compressed in the link given, compared to C which is nicely spaced out?
Show me stuff with overloads et al. Then verbosity goes through the roof.
Anyway, I'm not here to argue against using a language, I was just vilifying C++ and Objective C as a bit of a joke.
 
  • Thanks
Reactions: a6h
That last line of code is where the bug is. Never ever do that. And if you have to do it, then warn the reader = coder that things are not what they seem to be. The correct variable name is not "p", but "char *local_copy_of_ptr_do_not_modify_this_or_you_will_die = ptr". OK, maybe I'm exaggerating the variable name a little bit.

There's no bug, that's perfectly fine and done all the time. This is a simplistic, very simplistic, example of double free and how it is not
prevented by the assignment of p=NULL. My point.


One thing people need to understand: Pointers are not data. Integers, floats, strings, and things derived or aggregated from those are data.

No one said they are. All variable types in C can be pointers and/or data holders.



Pointers are metadata: something that describes the real data. And metadata is dangerous. So dangerous that you have to be careful with it.
No, pointers are variables. Period. Metadata is data about data. Metadata is a File Table in a file system. This is not the case here as a pointer is an address. It's totally confusing and wrong to introduce such a concept.


This is one of the reasons why I always suggest programming languages in which pointers become invisible to users. Doing memory management and tracking of which variable is store where is hard, tedious, and error-prone. It ought to be automated. We should have computers to help us do that, so we don't have to handle it ourselves. C's pointer type is what another old colleague refers to as a "foot-shaped gun": A tool that most of the time hurts you.

Then you've never run an OS without "hurt" because they're full of it. Drivers, memory, process management, the whole lot.
 
The problem is you do this implicitly every time you call a function that takes a pointer as an argument. This game of hot potato with dynamically-allocated memory reminds me of the classic sketch:

Me: Who frees this memory?
C: Yes
Me: No, I mean who is responsible for freeing this memory?
C: Yes, he is
Of course, this is a more "complex" example. I was giving a very basic example.

There's uncountable examples of functions that return a pointer to memory (I mean, every program would probably have it) and how you free (or don't) is most often the source of dangling memory, leaks and double de-referencing (the latter most often crashes your program very quickly anyway).

It often takes discipline, and if people don't have it, I advise them to not program in C.
 
Agreed. I see a lot of examples of this and for simple ones, it seems to make sense but for larger codebases if you then factor in that this pointer could be dangling almost everywhere else in the program, it seems a little bit ineffective to just set the local one to NULL. Especially since that will be inaccessible when the function ends anyway.

I got a little bit obsessed with this issue not too long ago and developed this: https://github.com/osen/stent

It basically provides a weak_ptr<T> for C (during debug mode only) so is effectively zero overhead and can detect all use after frees. As a bonus it also provides a typesafe vector<T> to avoid memory issues there. These days I actually find it safer than C++ and the potential that 'this' can dangle with smart pointers.
Would not the code crash on double de-referencing anyway?
Of course, when it crashes and where it crashes are a source of wonder for the programmer as they attempt to debug the mess.
 
Then you've never run an OS without "hurt" because they're full of it. Drivers, memory, process management, the whole lot.
I've spent 25 years writing code in C++ and C. Including operating system code (file systems), including kernel code. That doesn't mean that I want people to do it in the future. In particular not where the problem can easily be solved using programming languages that don't require the special care and discipline that C++/C require.
 
Back
Top