Let's try using pointer variables.
Pointer variable declaration
In the previous section, we explained three types of pointers.
Let's declare some pointer variables here to get a feel for how they work.
So, with that said, I'd like to show you an example of declaring a pointer variable now.
As it turns out, this is quite a tricky matter.
Let's start by showing two examples of declaring pointer variables of type int.
This is how you declare a pointer variable, as shown in many introductory texts.
These two are ways to declare a variable of pointer type to an int named p.
One way to write it appears to be *p, where * is a symbol indicating a pointer type.
In fact, we are declaring a variable 'p' that stores the address of an integer variable.
In that case, the second declaration with the asterisk in the type name also seems more readable, doesn't it?
Declaring more than one variable can cause subsequent ones to differ from the apparent type name.
In the following example, the second p2 will become a regular int variable.
It's a very troublesome issue because both ways of writing are extremely unclear.
For now, let's stick to the first writing style.
That means you can declare a pointer variable by putting an asterisk (*) before the variable name.
Even with a * attached, the variable name remains p.
Let's declare some pointer variables here to get a feel for how they work.
So, with that said, I'd like to show you an example of declaring a pointer variable now.
As it turns out, this is quite a tricky matter.
Let's start by showing two examples of declaring pointer variables of type int.
Source code
int *p;
int* p;
This is how you declare a pointer variable, as shown in many introductory texts.
These two are ways to declare a variable of pointer type to an int named p.
One way to write it appears to be *p, where * is a symbol indicating a pointer type.
In fact, we are declaring a variable 'p' that stores the address of an integer variable.
In that case, the second declaration with the asterisk in the type name also seems more readable, doesn't it?
Declaring more than one variable can cause subsequent ones to differ from the apparent type name.
In the following example, the second p2 will become a regular int variable.
Source code
int* p1, p2;
It's a very troublesome issue because both ways of writing are extremely unclear.
For now, let's stick to the first writing style.
That means you can declare a pointer variable by putting an asterisk (*) before the variable name.
Even with a * attached, the variable name remains p.
Assign an address.
As explained in the previous section, a pointer variable is a variable that holds an address.
Let's move on to assigning addresses to the pointer variable right away.
Okay, assigning an address is fine, but what address are you assigning?
In theory, if the number falls within the range of memory the computer has.
For example, a computer with 4GB of memory can handle any number within the range of 0 to 4 billion.
You can use them in that way for extremely simple computers like calculators, or for older gaming consoles like the Nintendo Famicom.
However, the computers you are likely using to learn C are probably modern ones.
Computers can be equipped with operating systems (OS) such as Windows, macOS, and Linux.
This is managed by a mechanism called virtual memory, which prevents you from arbitrarily using memory.
The mechanism by which the OS manages memory and appropriately allocates it to multiple applications. In an environment where numerous applications run simultaneously, if each application uses memory arbitrarily, memory used by different applications may overlap, causing them to malfunction. Therefore, the OS manages memory to prevent overlap between the memory used by individual applications.
Therefore, arbitrary address numbers will not be addresses managed by the OS.
Using pointer variables with arbitrary address assignments will likely be flagged as abnormal behavior by the OS and result in a crash.
Pointer variables must be assigned addresses managed by the operating system.
Actually, there is a simple and reliable way to assign properly managed address numbers.
The method is simple: declare another variable and assign the address of the original to it.
Declared variables can be used without issue because they are created in a memory area managed by the OS.
The following program demonstrates assigning a variable's address to a pointer variable p.
First, you can declare a variable as a pointer by placing an asterisk (*) before its name.
Please understand that an 'i' without a '*' prefix before its name indicates a regular variable.
In this example, we're using the & operator to obtain the address of variable i and assigning it to the pointer variable p.
In other words, at this point, the pointer variable p contains the address of i.
Therefore, the address of i and the content of the pointer variable p should naturally be the same.
The following program is an example of using the printf function to display and verify addresses.
The output of this program may be as follows.
They are perfectly aligned.
It's almost inevitable, considering pointer variables are variables themselves.
Because you're assigning &i to p and then immediately displaying that value.
However, be mindful of the type here.
The type of pointer variable p is a pointer to int.
The type of variable i is int, but the address obtained using the & operator is of pointer type.
Therefore, &i can be substituted for p, and both can be displayed using the %p specifier.
Let's move on to assigning addresses to the pointer variable right away.
Okay, assigning an address is fine, but what address are you assigning?
In theory, if the number falls within the range of memory the computer has.
For example, a computer with 4GB of memory can handle any number within the range of 0 to 4 billion.
You can use them in that way for extremely simple computers like calculators, or for older gaming consoles like the Nintendo Famicom.
However, the computers you are likely using to learn C are probably modern ones.
Computers can be equipped with operating systems (OS) such as Windows, macOS, and Linux.
This is managed by a mechanism called virtual memory, which prevents you from arbitrarily using memory.
Keyword
【Virtual memory】
The mechanism by which the OS manages memory and appropriately allocates it to multiple applications. In an environment where numerous applications run simultaneously, if each application uses memory arbitrarily, memory used by different applications may overlap, causing them to malfunction. Therefore, the OS manages memory to prevent overlap between the memory used by individual applications.
Therefore, arbitrary address numbers will not be addresses managed by the OS.
Using pointer variables with arbitrary address assignments will likely be flagged as abnormal behavior by the OS and result in a crash.
Pointer variables must be assigned addresses managed by the operating system.
Actually, there is a simple and reliable way to assign properly managed address numbers.
The method is simple: declare another variable and assign the address of the original to it.
Declared variables can be used without issue because they are created in a memory area managed by the OS.
The following program demonstrates assigning a variable's address to a pointer variable p.
Source code
int main(void)
{
int *p;
int i;
p = &i;
return 0;
}
First, you can declare a variable as a pointer by placing an asterisk (*) before its name.
Please understand that an 'i' without a '*' prefix before its name indicates a regular variable.
In this example, we're using the & operator to obtain the address of variable i and assigning it to the pointer variable p.
In other words, at this point, the pointer variable p contains the address of i.
Therefore, the address of i and the content of the pointer variable p should naturally be the same.
The following program is an example of using the printf function to display and verify addresses.
Source code
#include <stdio.h>
int main(void)
{
int *p;
int i;
p = &i;
printf("p = %p\n", p);
printf("&i = %p\n", &i);
return 0;
}
The output of this program may be as follows.
Results
p = 0012FF80
&i = 0012FF80
&i = 0012FF80
They are perfectly aligned.
It's almost inevitable, considering pointer variables are variables themselves.
Because you're assigning &i to p and then immediately displaying that value.
However, be mindful of the type here.
The type of pointer variable p is a pointer to int.
The type of variable i is int, but the address obtained using the & operator is of pointer type.
Therefore, &i can be substituted for p, and both can be displayed using the %p specifier.
Null pointer
Pointer variables also have random values assigned immediately after declaration. Since there's no way to know if that value is a valid address, using that address by mistake will definitely cause a bug.
To prevent this, we need a way to distinguish whether an address has been assigned. That's why C provides the null pointer.
Assigning the symbol NULL to a pointer variable indicates that no address has been assigned to it yet, meaning it is not yet usable.
int *p = NULL;
By doing this, you can use an if statement to compare p == NULL, allowing you to distinguish whether an address has been assigned to p.
To prevent this, we need a way to distinguish whether an address has been assigned. That's why C provides the null pointer.
Assigning the symbol NULL to a pointer variable indicates that no address has been assigned to it yet, meaning it is not yet usable.
int *p = NULL;
By doing this, you can use an if statement to compare p == NULL, allowing you to distinguish whether an address has been assigned to p.
Is a null pointer zero?
int *p = 0;
assigns a null pointer.
This is a fixed rule of C language syntax,
and does not mean that NULL is 0. NULL is always NULL.
NULL is an identifier value used to indicate that a valid address has not been assigned,
and it is clearly distinct from the numerical value 0 used for calculations.
That said, I believe most compilers treat NULL as 0...
assigns a null pointer.
This is a fixed rule of C language syntax,
and does not mean that NULL is 0. NULL is always NULL.
NULL is an identifier value used to indicate that a valid address has not been assigned,
and it is clearly distinct from the numerical value 0 used for calculations.
That said, I believe most compilers treat NULL as 0...
Mode switch
As explained in the previous section, pointer variables have two modes.
It is in both normal variable mode and pointer variable mode.
If you're using a pointer variable without any specific designation, it's in pointer variable mode.
To switch to normal variable mode, prefix the variable with an asterisk (*).
Pointer variables marked with an asterisk behave exactly like regular variables.
The following program demonstrates an example of switching pointer variables to standard variable mode.
The results of this program are as follows:
In this program, the pointer variable p is dereferenced by adding a * to it, switching it to normal variable mode.
p is a pointer variable p that has switched to normal variable mode.
As long as it's *p, you can treat it exactly like a regular variable.
Pointer variables switched to normal variable mode function just like regular variables.
The memory used at that time is the address assigned in pointer variable mode.In other words,
This is the most basic way to use a pointer variable.
Instead of directly specifying which memory address to overwrite,
Assign the memory address you want to rewrite, switch the mode, and rewrite it.
It's something of a tiered structure with two levels, so it might not be immediately obvious.
In the previous program, on line 5, the address of variable i was assigned to the pointer variable p.
In line 6, p is switched to normal variable mode, and 10 is assigned to the address stored in p.
At this time, the address that p stored is, in other words, the address of variable i.
As a result, the value of variable i will be overwritten to 10.
If I could explain this more specifically, at that time, variable i and the *p in normal variable mode,
It means they are using the exact same memory space.
It's not to say that when you assign 10 to *p*, *i* automatically switches to 10 as well.
These two are pointing to the same memory location.
It is in both normal variable mode and pointer variable mode.
If you're using a pointer variable without any specific designation, it's in pointer variable mode.
To switch to normal variable mode, prefix the variable with an asterisk (*).
Pointer variables marked with an asterisk behave exactly like regular variables.
The following program demonstrates an example of switching pointer variables to standard variable mode.
Source code
#include <stdio.h>
int main(void)
{
int *p;
int i;
p = &i;
*p = 10; /* Assign to a pointer variable switched to normal variable mode */
printf("*p = %d\n", *p);
printf("i = %d\n", i);
return 0;
}
The results of this program are as follows:
Results
*p = 10
i = 10
i = 10
In this program, the pointer variable p is dereferenced by adding a * to it, switching it to normal variable mode.
p is a pointer variable p that has switched to normal variable mode.
As long as it's *p, you can treat it exactly like a regular variable.
Pointer variables switched to normal variable mode function just like regular variables.
The memory used at that time is the address assigned in pointer variable mode.In other words,
The most basic usage of pointer variables
Assign the memory address you wish to read or write to when in pointer variable mode,
then switch to normal variable mode to manipulate that memory.
then switch to normal variable mode to manipulate that memory.
This is the most basic way to use a pointer variable.
Instead of directly specifying which memory address to overwrite,
Assign the memory address you want to rewrite, switch the mode, and rewrite it.
It's something of a tiered structure with two levels, so it might not be immediately obvious.
In the previous program, on line 5, the address of variable i was assigned to the pointer variable p.
In line 6, p is switched to normal variable mode, and 10 is assigned to the address stored in p.
At this time, the address that p stored is, in other words, the address of variable i.
As a result, the value of variable i will be overwritten to 10.
If I could explain this more specifically, at that time, variable i and the *p in normal variable mode,
It means they are using the exact same memory space.
It's not to say that when you assign 10 to *p*, *i* automatically switches to 10 as well.
These two are pointing to the same memory location.
Strange symbols*
The * symbol actually has three distinct meanings, which can cause confusion. Here, we will clearly distinguish between the three. The first is the multiplication operator. This refers to the multiplication operation. It is a symbol used within expressions, such as kai = 5 * 8.
The second is the indirect reference operator. It converts a pointer variable to normal variable mode.
This symbol is used within expressions, like *p.
Since pointer variables cannot be multiplied while in pointer variable mode,
using the same symbol as the multiplication operator allows them to be distinguished.
The third is the symbol used when declaring a pointer variable. It is only used during declaration, like int *p.
This is where it gets a bit confusing: the * used by the indirection operator to switch to pointer variable mode and the * used during declaration are completely different symbols with no relation whatsoever.
It's purely coincidental that they happen to use the same character.
I believe it would be clearer if all three used different characters.
Assigning the same character is one of the flaws of the C language.
But since it can't be fixed now,
please be sure to recognize that these three are symbols with distinct meanings.
The second is the indirect reference operator. It converts a pointer variable to normal variable mode.
This symbol is used within expressions, like *p.
Since pointer variables cannot be multiplied while in pointer variable mode,
using the same symbol as the multiplication operator allows them to be distinguished.
The third is the symbol used when declaring a pointer variable. It is only used during declaration, like int *p.
This is where it gets a bit confusing: the * used by the indirection operator to switch to pointer variable mode and the * used during declaration are completely different symbols with no relation whatsoever.
It's purely coincidental that they happen to use the same character.
I believe it would be clearer if all three used different characters.
Assigning the same character is one of the flaws of the C language.
But since it can't be fixed now,
please be sure to recognize that these three are symbols with distinct meanings.
namely, a shortcut
We have now explained all the functionalities of pointer variables.
In fact, pointers have no functions beyond what has been explained so far.
When in pointer variable mode, assign a memory address.
That's the full functionality of pointers: switching to normal variable mode and then manipulating that memory.
Given what we've covered so far, it's natural that questions will arise.
Ultimately, what practical purpose do pointers serve?
As stated in the preceding section, to assign the variable's address in pointer variable mode,
What's the point of switching to normal variable mode to do something like that?
This is exactly as I suspected, and it's useless in this way.
It's generally much easier and less prone to errors to manipulate variables directly.
The true use of pointers is to use them as shortcuts.
It's just like those shortcuts on your Windows desktop.
A shortcut is a file that points to a file located elsewhere.
Opening the shortcut will open the file it points to.
Despite this, a shortcut is not the file it points to.
You can create shortcuts wherever you like.
Creating or deleting multiple instances will have no effect on the pointed-to file.
This is precisely what a pointer does.
If you store the address of an existing variable in a pointer variable,
Wherever the pointer variable is usable, it may be in a place where the original variable is not.
If you switch a pointer variable to a regular variable mode, you can use it just like the original variable.
That's exactly how it can act as a shortcut.
In fact, pointers have no functions beyond what has been explained so far.
When in pointer variable mode, assign a memory address.
That's the full functionality of pointers: switching to normal variable mode and then manipulating that memory.
Given what we've covered so far, it's natural that questions will arise.
Ultimately, what practical purpose do pointers serve?
As stated in the preceding section, to assign the variable's address in pointer variable mode,
What's the point of switching to normal variable mode to do something like that?
This is exactly as I suspected, and it's useless in this way.
It's generally much easier and less prone to errors to manipulate variables directly.
The true use of pointers is to use them as shortcuts.
It's just like those shortcuts on your Windows desktop.
A shortcut is a file that points to a file located elsewhere.
Opening the shortcut will open the file it points to.
Despite this, a shortcut is not the file it points to.
You can create shortcuts wherever you like.
Creating or deleting multiple instances will have no effect on the pointed-to file.
This is precisely what a pointer does.
If you store the address of an existing variable in a pointer variable,
Wherever the pointer variable is usable, it may be in a place where the original variable is not.
If you switch a pointer variable to a regular variable mode, you can use it just like the original variable.
That's exactly how it can act as a shortcut.
Foreign language pointers
Generally, pointers are said to be a feature unique to C and C++. Indeed, in the sense of manipulating the address of specified memory, that is true.
However, the true purpose of pointers is to serve as shortcuts, and from that perspective, practically all practical languages have pointers. Java references are precisely such a feature, used frequently, and Visual Basic's SET statements can be considered similar.
Fundamentally, without pointers, complex data structures like linked lists or trees cannot be implemented, and object-oriented programming becomes difficult.
In that sense, C language pointers, whose mechanism is clear, are easier to understand than Java or Visual Basic pointers, whose mechanisms are unclear.
The biggest difference between references in other languages and C pointers is whether they are automatic or manual.
References in other languages are mostly automatic, functioning as shortcuts,
while C pointers are entirely manual; programmers must fully understand and use them.
In return, when advanced programmers master C pointers, they become an incredibly powerful feature. Using pointers alone, you can implement almost any control structure and any data structure.
In fact, most of C's functionality is built on pointers.
However, the true purpose of pointers is to serve as shortcuts, and from that perspective, practically all practical languages have pointers. Java references are precisely such a feature, used frequently, and Visual Basic's SET statements can be considered similar.
Fundamentally, without pointers, complex data structures like linked lists or trees cannot be implemented, and object-oriented programming becomes difficult.
In that sense, C language pointers, whose mechanism is clear, are easier to understand than Java or Visual Basic pointers, whose mechanisms are unclear.
The biggest difference between references in other languages and C pointers is whether they are automatic or manual.
References in other languages are mostly automatic, functioning as shortcuts,
while C pointers are entirely manual; programmers must fully understand and use them.
In return, when advanced programmers master C pointers, they become an incredibly powerful feature. Using pointers alone, you can implement almost any control structure and any data structure.
In fact, most of C's functionality is built on pointers.
About This Site
Learning C language through suffering (Kushi C) isThis is the definitive introduction to the C language.
It systematically explains the basic functions of the C language.
The quality is equal to or higher than commercially available books.




