From f471f891e017d0ccf4fbb04f58404eb40b9a78a0 Mon Sep 17 00:00:00 2001 From: thomasabishop Date: Sun, 8 Feb 2026 19:22:03 +0000 Subject: [PATCH] tweaks to C notes --- zk/Char_data_type_in_C.md | 35 +++++++++++++++++------------------ zk/Macros_in_C.md | 35 ++++++++++++++++++++++++++--------- zk/Pointers_in_C.md | 17 +++++++++-------- 3 files changed, 52 insertions(+), 35 deletions(-) diff --git a/zk/Char_data_type_in_C.md b/zk/Char_data_type_in_C.md index 0ee3f07..6bdc16a 100644 --- a/zk/Char_data_type_in_C.md +++ b/zk/Char_data_type_in_C.md @@ -60,30 +60,17 @@ In memory this would actually be: With each char corresponding to an ASCII number apart from the null which would just be `0000 0000`. -### String literals - -The easiest way to declare a string as a `char` array is to use the format we've -already used which is string literal notation: - -```c -char word[] = "Hello"; -``` - -The null terminator is implied in this form, you do not need to add it manually. -Also the length is fixed to the length of the string (in this case `6` for the -five actual characters plus the null). - -### Non-literal string declaration - The more formal way of doing this would be: ```c char word[6] = {'H', 'e', 'l', 'l', 'o', '\0'} ``` -However, in practice, if you just want quick access to a string, where you don't -need to modify the individual characters later, you can just use a direct -pointer definition: +### String literals + +In practice, if you just want quick access to a string, where you don't need to +modify the individual characters later, you can just use a direct pointer +definition: ```c char *name = "Thomas"; @@ -94,3 +81,15 @@ is a string literal and is stored as read-only. It can be redefined (the pointer can point to something else) but it's not mutable itself. More info in [Pointers in C](./Pointers_in_C.md). + +Note that the `*` in the declaration is part of the type definition, it's +signalling that its a pointer to a string literal, it's not +referencing/dereferencing or doing anything to the bytes. + +Technically you could write: + +```c +char* name = "Thomas" +``` + +This would be clearer but it is not the convention. diff --git a/zk/Macros_in_C.md b/zk/Macros_in_C.md index 2b37f99..a0e4b04 100644 --- a/zk/Macros_in_C.md +++ b/zk/Macros_in_C.md @@ -3,14 +3,35 @@ tags: - C --- -Think of them as a find and replace that takes place before compilation. +Think of macros as a find and replace that takes place before compilation at the +[pre-processor](./C_compilation_process.md) stage. -They are ephemeral and never make it into the compiled code. +They are ephemeral and never make it into the compiled code in the form they are +defined as. -With a macro, the computation happens "inline" without having to call functions -which make costly alterations to the stack. +When the preprocessor injects the value, the injection happens "inline" without +having to call functions which make costly alterations to the stack, which is +the main benefit - efficiency. -A function and function call such as: +Starting with a simple example: + +```c +#define NAME "Thomas" +``` + +This is not actually a variable because it has no memory address. It never makes +it to memory-assignation because it doesn't exist after pre-processing. By the +compilation stage,j this value has been added to the code as a type +corresponding to the literal you defined; in this case a string literal +(`char *`). To emphasise, the macro itself has no type because it doesn't exist +at the type level (compilation), the data type it represents after injection is +applied by the compiler through parsing. + +> The convention is to have macros in `ALL_CAPS` to distinguish them from real +> variables. Don't confuse them for constants, constants are actually written in +> lowercase like other actual variables. + +To use a more complex example, a function and function call such as: ```c int square(int x) { return x * x; } @@ -32,7 +53,3 @@ int a = ((5) * (5)); ``` after pre-processing but before compilation. - -## Syntax - -`#define` always creates a macro but there are different types. diff --git a/zk/Pointers_in_C.md b/zk/Pointers_in_C.md index 9f5a79b..7fdc531 100644 --- a/zk/Pointers_in_C.md +++ b/zk/Pointers_in_C.md @@ -48,13 +48,17 @@ char *name = "Thomas"; ``` Then to reference the value (_not_ the address, the actual value) you just use -`name`. +`name`. The `*` is just part of the type definition in the above - it's just +signalling the type. If you later want to change the value, you then use `*` as +an operator: -This is confusing but I just have to accept for now. +```c +*name = 'Tom'; +``` -Note that if you do this, it creates the string in read-only memory. You can't -modify the individual characters of `"Thomas"`. To do this you would need to -define it as: +Note that if you use a pointer to `char`, it creates the string in read-only +memory. You can't modify the individual characters of `"Thomas"`. To do this you +would need to define it as: ```c char name[] = "Thomas"; @@ -85,6 +89,3 @@ Or, using a variable: static char *topic = "test_topic"; mqtt_publish(mqtt_client, topic, "Test message"); ``` - -> Note in the above the `*` is part of the type definition, _not_ the variable. -> Even more confusing!