tweaks to C notes
This commit is contained in:
parent
9dcae3ac16
commit
f471f891e0
3 changed files with 52 additions and 35 deletions
|
|
@ -60,30 +60,17 @@ In memory this would actually be:
|
||||||
With each char corresponding to an ASCII number apart from the null which would
|
With each char corresponding to an ASCII number apart from the null which would
|
||||||
just be `0000 0000`.
|
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:
|
The more formal way of doing this would be:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
char word[6] = {'H', 'e', 'l', 'l', 'o', '\0'}
|
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
|
### String literals
|
||||||
need to modify the individual characters later, you can just use a direct
|
|
||||||
pointer definition:
|
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
|
```c
|
||||||
char *name = "Thomas";
|
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.
|
can point to something else) but it's not mutable itself.
|
||||||
|
|
||||||
More info in [Pointers in C](./Pointers_in_C.md).
|
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.
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,35 @@ tags:
|
||||||
- C
|
- 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
|
When the preprocessor injects the value, the injection happens "inline" without
|
||||||
which make costly alterations to the stack.
|
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
|
```c
|
||||||
int square(int x) { return x * x; }
|
int square(int x) { return x * x; }
|
||||||
|
|
@ -32,7 +53,3 @@ int a = ((5) * (5));
|
||||||
```
|
```
|
||||||
|
|
||||||
after pre-processing but before compilation.
|
after pre-processing but before compilation.
|
||||||
|
|
||||||
## Syntax
|
|
||||||
|
|
||||||
`#define` always creates a macro but there are different types.
|
|
||||||
|
|
|
||||||
|
|
@ -48,13 +48,17 @@ char *name = "Thomas";
|
||||||
```
|
```
|
||||||
|
|
||||||
Then to reference the value (_not_ the address, the actual value) you just use
|
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
|
Note that if you use a pointer to `char`, it creates the string in read-only
|
||||||
modify the individual characters of `"Thomas"`. To do this you would need to
|
memory. You can't modify the individual characters of `"Thomas"`. To do this you
|
||||||
define it as:
|
would need to define it as:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
char name[] = "Thomas";
|
char name[] = "Thomas";
|
||||||
|
|
@ -85,6 +89,3 @@ Or, using a variable:
|
||||||
static char *topic = "test_topic";
|
static char *topic = "test_topic";
|
||||||
mqtt_publish(mqtt_client, topic, "Test message");
|
mqtt_publish(mqtt_client, topic, "Test message");
|
||||||
```
|
```
|
||||||
|
|
||||||
> Note in the above the `*` is part of the type definition, _not_ the variable.
|
|
||||||
> Even more confusing!
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue