2025-12-15 17:26:02 +00:00
|
|
|
---
|
|
|
|
|
tags:
|
|
|
|
|
- C
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
A pointer is a reference to the address of a variable in memory.
|
|
|
|
|
|
|
|
|
|
```c
|
2026-01-19 17:06:41 +00:00
|
|
|
int x = 27;
|
|
|
|
|
int *ptr = &x;
|
2025-12-15 17:26:02 +00:00
|
|
|
|
2026-01-19 17:06:41 +00:00
|
|
|
printf("%i\n", x);
|
2025-12-15 17:26:02 +00:00
|
|
|
// 27
|
|
|
|
|
|
|
|
|
|
|
2026-01-19 17:06:41 +00:00
|
|
|
printf("%p\n", *ptr);
|
2025-12-15 17:26:02 +00:00
|
|
|
// 0x7ffeb44f7eac
|
|
|
|
|
```
|
|
|
|
|
|
2026-01-19 17:06:41 +00:00
|
|
|
The `&` and `*` is frankly confusing.
|
2025-12-15 17:26:02 +00:00
|
|
|
|
2026-01-19 17:06:41 +00:00
|
|
|
In the previous example, `int *ptr = &x`, `ptr` is a variable that holds the
|
|
|
|
|
memory address of `x`. `*` signals that it is a pointer variable, `&` is what
|
|
|
|
|
does the retrieval.
|
2025-12-15 17:26:02 +00:00
|
|
|
|
2026-01-19 17:06:41 +00:00
|
|
|
In the following:
|
2025-12-15 17:26:02 +00:00
|
|
|
|
|
|
|
|
```c
|
2026-01-19 17:06:41 +00:00
|
|
|
int x = 27;
|
|
|
|
|
int *ptr = &x;
|
|
|
|
|
int value = *ptr;
|
2025-12-15 17:26:02 +00:00
|
|
|
```
|
|
|
|
|
|
2026-01-19 17:06:41 +00:00
|
|
|
We again set `ptr` to the memory address of `x`, but we use `*` on the last line
|
|
|
|
|
to **de-reference** the pointer and get the original value back. Thus `value`
|
|
|
|
|
becomes equal to `27`.
|
2025-12-15 17:26:02 +00:00
|
|
|
|
2026-01-19 17:06:41 +00:00
|
|
|
Pointers are necessary because C uses a [call by value](./C_is_call_by_value.md)
|
|
|
|
|
system for function arguments.
|
2026-02-08 18:39:09 +00:00
|
|
|
|
|
|
|
|
## To use a pointer you don't have to declare the value first (confusing)
|
|
|
|
|
|
|
|
|
|
It is totally legitimate to declare a pointer in one go, especially with
|
|
|
|
|
strings:
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
char *name = "Thomas";
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Then to reference the value (_not_ the address, the actual value) you just use
|
|
|
|
|
`name`.
|
|
|
|
|
|
|
|
|
|
This is confusing but I just have to accept for now.
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
char name[] = "Thomas";
|
|
|
|
|
name[0] = "t";
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Here is a real example of me doing this:
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
void mqtt_publish(esp_mqtt_client_handle_t client, char *topic,
|
|
|
|
|
const char *payload)
|
|
|
|
|
{
|
|
|
|
|
if (MQTT_CONNECTED) {
|
|
|
|
|
esp_mqtt_client_publish(client, topic, payload, strlen(payload), 0, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
And then when calling the function:
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
mqtt_publish(mqtt_client, "test_topic", "Test message");
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Or, using a variable:
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
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!
|