Re: [PIC] Learning C

Christopher Head <[email protected]>
Newsgroups gmane.comp.hardware.microcontrollers.pic
Message-ID <[email protected]>
On Tue, 19 Nov 2024 11:54:46 -0700
"Harold Hallikainen" <[email protected]> wrote:

> On learning C, I really like it, but could use more knowledge on
> pointers, void types, and use of CONST. I generally think CONST means
> it is constant, does not change, and could be stored in flash. But
> I've seen stuff where that does not seem to be the case.

Here are a couple of things I can write a bit about! I think some
confusion probably stems from the fact that the same word means
different things depending on the context (a statement true of both
void and const).

Regarding void:

Used as the return type of a function, it means “nothing”—i.e. the
function doesn’t return anything. “int f(int x) { return x + 1; }”, the
function “f” returns an int. “void g(int x) { do_something_with(x); }”,
the function “g” doesn’t return anything at all. Pretty simple.

Used as part of a pointer, it means “unknown” or “unspecified”—i.e. if
you have “void *p”, it doesn’t mean “p is a pointer to nothing”, it
means “p is a pointer to something, but I’m not saying *what*”. It
might point at one or more ints. It might point at one or more doubles.
It might point at one or more instances of some struct. Before you can
do anything concrete with it, you have to convert it to some other
pointer type.

Regarding const:

Used for a variable itself (e.g. “const int x”), it means you promise
not to modify “x”, and the compiler will help you keep that promise as
well as it can. On an MCU, the compiler MAY put it in Flash/ROM/etc.. On
a PC, the compiler MAY put it in a section of the executable file that
gets mapped read-only so you get a crash if you try to write to it.
Neither of these is guaranteed, just typical. The compiler helps you by
making something like “x = 27;” or “int *p = &x;” errors (or at the
very least warnings); however, as is often the case, casting allows you
to do things the compiler can’t check, and then it’s up to you to make
sure you’re keeping your promise.

Because of the confusing shape of declarations of variables of pointer
type, “int * const p” is another example of this. The “const” is to the
right of the asterisk, and it means “p is const”. In other words, “I
promise not to modify p”. You’re welcome to modify whatever p points
at, just not p itself. People often recommend reading points
right-to-left, so this can be read as “p is a const pointer to int”
(the pointer is const, the int is not).

Used for the target of a pointer (e.g. “const int *p” or “int const
*p”, read as “p is a pointer to an int const/const int”), it means you
intend not to modify the thing pointed at THROUGH THIS POINTER. It does
NOT mean the thing pointed at won’t be modified! For example, “int x =
1; const int *p = &x; x = 2;” is perfectly legitimate; you modified “x”,
just not through “p”. You can bypass this rule via a cast; it’s meant
as a helpful tool, not a straightjacket. Generally this is most useful
for function parameters, where “void f(int *p)” suggests that the
function may modify the pointed-to int (though there’s no requirement
for it to do so), while “void f(const int *p)” suggests that it won’t
(technically it can, by casting, but that would be considered unusual
and ought to be called out loudly in the documentation). In neither
case does it mean you have to pass a pointer to a const int; rather,
it’s just telling you whether to expect calling “f” to modify the int
or not.

It is, I think, also technically valid C to write “int x;” in one
translation unit (typically a source file) and “extern const int x;” in
another (typically a header file) to create a variable that can only be
modified in one source file, but read elsewhere. That’s pretty rare
though.

Finally, I’d recommend enabling as many compiler warnings as you
possibly can. There will be false positives. There will also be true
positives and you’ll be thankful for them. Personally I like to use
-Werror, which turns all warnings into errors, and then use my
compiler’s provided method to silence specific warnings in places where
I know they’re wrong (in the case of GCC, this is “#pragma GCC
diagnostic”).
-- 
Christopher Head
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.