This question already has answers here:
What exactly is meant by "de-referencing a NULL pointer"?
(8 answers)
Closed 5 years ago.
I am studying C at school , and I am facing a problem with pointers , Why does this unhandled error rise (im using visual studio 2013 express for desktop on 64 bit windows 10) , when I try to run the code below.
My question is , Why is this happening?
Code Block :
// ~~ Libraries Or Header Files. ~~ //
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ~~ Main Function ~~ //
int main(void)
{
// ~ Variables ~ //
int * p = NULL;//#define NULL ((void *)0)
printf(*p);
//printf(p)l also raises an error.
// ~ END ~ //
system("PAUSE");
return 0;
}
Error:
" Unhandled exception at 0x009A3C2A in hwQ3.exe: 0xC0000005: Access violation
reading location 0x00000000 ".
There are two problems with this code.
First, printf expects its first argument to be a format string, and the type of the argument is assumed to be const char * (it's a pointer to the first character in a zero-terminated string). Since the object p has type int *, the expression *p has type int, so it's the wrong type, and the value of *p isn't a valid address of a string, because...
You've initialized p to NULL. NULL is an invalid pointer value that's guaranteed to compare unequal to any valid pointer value (it's a well-defined "nowhere" value). When you write *p, you're saying, "I want the value of the integer object p points to." Since p points "nowhere", the behavior of the operation is undefined, and one possible result of undefined behavior is a segfault.
So...
If you want to print the value of the integer object that p points to, you would write something like
printf( "%d\n", *p );
but only after you do a sanity check on p to make sure it isn't NULL:
if ( p ) // or p != NULL
printf( "%d\n", *p );
Valid pointer values are obtained by one of the following methods:
Using the unary & operator on an lvalue (an expression that refers to an object in memory such that the object may be read or updated):
p = &x; // x is an integer object
p = &a[i]; // a is an array of integer, so a[i] is an integer object
p = &foo.bar; // foo is a struct with an int member named bar, so foo.bar is an integer object
etc.
Calling one of malloc, calloc, or realloc:
p = malloc( sizeof *p );
Using an array expression in most circumstances. Unless it is the operand of the sizeof or unary & operators, or is a string literal being used to intialize a character array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array. In the case of printf, when we write
printf( "this is a test\n" );
the type of the string literal "this is a test\n" is converted from type "16-element array of char" to "pointer to char", and its value is the address of the first character in the string - that address value is what actually gets passed to printf.
The first argument to printf(...) is a const char *format so in both cases you're trying to dereference a NULL pointer. That causes you to access memory outside your allowable range (at zero).
Basic information about pointers:
Pointers are to declare a pointer variable, set it to point somewhere, and finally manipulate the value that it points to. A simple pointer declaration looks like this:
int *ip;
Pointers are generated with the address-of'' operator &, which we can also think of as thepointer-to'' operator. Demonstrating this by declaring (and initializing) an int variable i, and then setting ip to point to it:
int i = 5;
ip = &i;
Example pointer usage:
#include <stdio.h>
int main(){
int var =10;
int *ptr = &var;
printf("%d\n", *ptr);
return 0;
}
What happens when you deference the pointer to NULL?
int *a = NULL; // a is a null pointer
int b = *a; // CRASH: dereferencing a, trying to read it
*a = 0; // CRASH: dereferencing b, trying to write it
Related
I have a basic doubt, when we de-reference a pointer to an array why we get name of the array instead the value of first member of an array, I see this has been asked here but I didn't get it
exactly how?
dereferencing pointer to integer array
main()
{
int var[10] = {1,2,3,4,5,6,7,8,9,10};
int (*ptr) [10] = &var;
printf("value = %u %u\n",*ptr,ptr); //both print 2359104. Shouldn't *ptr print 1?
}
So, is it like when we dereference a pointer, it cancel out the reference operator and what we get is variable name, and in case of pointer to an array, it is the array name ?
main()
{
int a = 10;
int *p = &a;
printf("%d\n", *p) /* p = &a; *p = *(&a); and having a dereference cancel out the &, gives us *p = a ? */
}
Because ptr has type int (*)[10] which is a pointer to an array, *ptr has type int[10] which is an array type.
This array decays to a pointer to its first element when it is passed to printf which then prints the pointer value. The result would be the same if you passed var to printf instead of *ptr.
You do not get a variable name when you dereference a pointer. If the pointer points to an object the you get that object. If it does not point to an object then you get undefined behavior. In particular, if the pointer points to a whole array, then you get that array. That's a fundamental aspect of how pointers work.
However, a fundamental aspect of how arrays work is that in most contexts, an expression of array type is automatically converted to a pointer to the first array element. This address corresponds to the address of the array itself, but has different type (int * in your case, as opposed to int (*)[10]). Typically, converting these to an integer type produces the same value. Thus, in your example code, *ptr is equivalent to var, and each is automatically converted to a pointer of type int *, equivalent to &var[0].
But note also that it is not safe to convert pointers to integers by associating them with printf directives, such as %u, that expect a corresponding integer argument. The behavior is undefined, and in practice, surprising or confusing results can sometimes be observed. One prints a pointer value with printf by using a %p directive, and converting the pointer value to type void *. Example:
printf("pointer = %p %p\n", (void *)*ptr, (void *)ptr);
Combined with the type and value of ptr from your example, this can be expected to reliably print two copies of the same hexadecimal number.
A char pointer can be assigned an arbitrary string but an integer pointer cannot be assigned an integer. Since both of them are pointers and contains address. Why is assigning string valid but an integer invalid in C to a pointer before dynamic allocation.
#include<stdio.h>
int main()
{
char *s = "sample_string"; // valid
printf("%s\n", s);
int *p = (int)5; // invalid
printf("%d\n", *p);
return 0;
}
Which gives output :
sample_string
Segmentation fault (core dumped)
What is the reason behind it? Although both of them are invalid in C++.
There is no "string type" in C. A "string", by C definition, is an array of char with a zero byte at the end.
The type of "sample_string" is char[14], which can be assigned to a pointer.
The type of (int)5 is int, which cannot[1].
The segmentation fault happens because you are accessing the address 0x00000005, which is not valid.
[1]: Technically you can. But if you want to dereference that pointer successfully, you have to take care that the address value of that integer has the proper alignment for the type, and is referring to a valid object of the type. Which is why compilers generate a warning if you don't explicitly cast that integer to pointer type in the assignment, to indicate that you do know what you're doing.
char *s = "sample_string"; Here "sample_string" is a string literal which is a const char[] in C++. It's implicitly converted to const char*. You'll get a warning though since you're assigning it to a char*.
int *p = (int)5; Here 5 is just an integer. Since you're assigning this a pointer, that means it's an invalid pointer value. And hence when it's referenced, you get a segfault.
This is simple:
A char object may hold a char value: char x = 'a';.
An int object may hold an int value: int x = 3;.
A char * object may point to an array of char: char *p = "abc";.
An int * object may point to an array of int: int *p = (int []) {1, 2, 3};.
(In this answer, “point to an array” is short for “point to the first element of an array”.)
In C, a string literal, such as "abc", is effectively an array of char, including a null character at the end. Also, the text above, (int []) {1, 2, 3}, is a compound literal that creates an array of int. So both "abc" and (int []) {1, 2, 3} are arrays. When an array is assigned to a pointer, the C implementation automatically converts it to a pointer to its first element. (This conversion occurs whenever an array is used in any expression other than as the operand of sizeof, as the operand of unary &, or, if it is a string literal, as the initializer for an array.)
The convention is that strings are arrays of char (char[]) and a pointer to a string points to the first element of this char array, similar like a pointer to an array always points to its first element by default, i.e for an int array
int a[10];
int *p;
p=&a
points to the first element of a that is a[0] in index notation
but an integer pointer cannot be assigned an integer.
Not quite. In C an integer can be assigned to a pointer - with certain conditions. Yet this only sets the pointer to 5, not that p points to an int with the value of 5. *p attempts to read what is at address 5 and interpret that location as an int. Certainly access to address 5 is invalid and causes a seg fault.
Even if those conditions are met (see below), this is certainly not what OP is seeking which I assume to be set the pointer p to point to someplace with the value/type of 5/int in it.
(int) {5} is a compound literal, available since C99. Here it is an int with the value of 5 and code takes the address of that object and assigns that address to p.
// int *p = (int)5;
int *p = & ((int) {5});
printf("%d\n", *p); // prints 5
An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation. C17dr § 6.3.2.3 5
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I was expecting a garbage value from the first printf() statement but I got the address instead. Why?
#include<stdio.h>
int main()
{
int (*p)[10];
int a[10]={1,2,3,4,5,6,7,8,9,0};
p=a+10;
printf("%d\n",*(p));
printf("%u",(p));
}
For starters this statement
p=a+10;
is invalid.
The left side of the assignment has the type int( * )[10] while the right side of the assignment has the type int * and there is no implicit conversion from one type to another.
You have to write
p = ( int( * )[10] )( a + 10 );
Secondly these calls of printf
printf("%d\n",*(p));
printf("%u",(p));
have undefined behavior because there are used invalid conversion specifier d and u with arguments of pointer types because *p and p are both pointers.
So a valid program can look the following way
#include <stdio.h>
int main(void)
{
int (*p)[10];
int a[10]={1,2,3,4,5,6,7,8,9,0};
p = ( int( * )[10] )( a + 10 );
printf("%p\n",( void * )*p );
printf("%p\n", (void *)p );
return 0;
}
A pointer may point to the memory that follows the last element of an object (or an array).
So after this statement
p = ( int( * )[10] )( a+10 );
the pointer p points after the first element of an imagined two-dimensional array elements of which in turn one-dimensional arrays of the type int[10] and the first element of the imagined two-dimensional array corresponds to the array a.
The expression *p is also a pointer. Its type is int * because the expression *p gives an lvalue of the type int[10] and in expressions this lvalue is implicitly converted to pointer to its first element (in this case of the type int).
So the both expressions p and *p points to the same memory and have the same value.
This is demonstrated by the program output
0x7ffcfd46ea48
0x7ffcfd46ea48
The difference between these two pointers, p and *p, is the type of an object they potentially point to.
Consider the following demonstrative program
#include <stdio.h>
int main(void)
{
int (*p)[10];
int a[10]={1,2,3,4,5,6,7,8,9,0};
p = ( int( * )[10] )( a+10 );
printf("%zu\n",sizeof( *p ) );
printf("%zu\n",sizeof( **p ) );
return 0;
}
Its output is
40
4
You could get undefined behavior if you wrote
printf( "%d\n", **p );
In this case the expression **p has the type int and there is an access to the memory beyond the array a.
Given this declaration:
int (*p)[10];
p is a pointer to an array. The expression *p therefore designates the pointed-to array itself. But in almost all C contexts, including in particular when it is an argument in a function call expression, the value of an expression of array type is automatically converted to a pointer to the first element of the array. The address of that element is the same as the address of the array itself, so if p is in fact a valid pointer then it is entirely reasonable for
printf("%p\n", (void *) (*p));
printf("%p\n", (void *) (p));
to print two identical lines.
Do note, however, the use of the %p format directive instead of %u or %d for printing a (void) pointer value, and the casts to void *. These changes to your original code are necessary for the behavior of the printf calls to be well defined.
It is true that as far as the C language is concerned, *p does not designate an object in your case, so in that sense, evaluating the expression *p produces undefined behavior. This is one of the reasons why I say only that it is "reasonable" for the code to emit two identical lines. In practice, however, implementations are likely to treat the expression *p identically to (int *) p, whose behavior is well-defined in this case.
You should also be aware -- and your compiler should be warning you -- that the expression a + 10 has the wrong type (int *) to be assigned directly to your p (an int (*)[10]). It is allowed to convert between those two types, but a cast is required:
p = (int (*)[10])(a + 10);
or
p = (void *)(a + 10);
There is good reason to expect that your compiler is compiling the original assignment expression as if the required cast were present, especially inasmuch as it is a no-op in many implementations, probably including yours, but you should not rely on that.
The array can be treated as (decays to) a pointer to the first element.
When you take the address of an array, you generate a pointer to the array, generally to the same address as first element
When you dereference the pointer to array, you get pointer to element, which generally has the same actual numeric value.
I say generally, because some strange C emulator, or some system that puts an extra indirection in all pointer objects, might decide that the array and the content of the array are 2 different objects.
I am trying to understand the significance of these two operators, so I wrote this code just for that purpose.
#include <stdio.h>
#include <string.h>
int main()
{
char *mnemonic, *operands;
mnemonic = "add";
operands = "five to two";
analyse_inst(mnemonic, operands);
}
void analyse_inst(char mnemonic, char operands)
{
printf("%s", mnemonic);
printf("%s", operands);
}
However, I noticed that it wouldn't work unless I change the arguments of analyse_inst() function to analyse_inst(char * mnemonic, char * operands), which means that I will be passing pointers to the function. But why is that required?
Also, I looked up about "passing by reference." And according to tutorialspoint.com, its definition:
The call by reference method of passing arguments to a function copies
the address of an argument into the formal parameter. Inside the
function, the address is used to access the actual argument used in
the call. It means the changes made to the parameter affect the passed
argument.
From that, I got that passing a variable by reference and then modifying that value would mean that the same variable outside the function would be changed as well; whereas for passing a variable by value would not change the same variable located outside the function.
Am I going wrong anywhere?
How can I can modify my code such that I am passing the two variables by reference?
(P.S. I have read other Stack Overflow threads on the same topic, but I would appreciate it if anyone could explain it in the context of the code I wrote)
which means that I will be passing pointers to the function. But why is that required?
Because what you have in main are pointers, and what printf("%s" expects is a char*.
"Pass by reference" is a broad term in programming, meaning passing along an address rather than a copy of the object. In your case, you pass a pointer to the first element of each string, rather than making a copy of the whole string, since that would waste execution time and memory.
So while the strings themselves could be said to be "passed by reference", strictly speaking C actually only allows parameters to be passed by value. The pointers themselves are passed by value. Your function parameters will be copies of the pointers you have allocated in main(). But they point at the same strings as the pointers in main() do.
From that, I got that passing a variable by reference and then modifying that value would mean that the same variable outside the function would be changed as well;
Indeed, you could change the string from inside the function through the pointer and then it would affect the string in main(). But in this case, you haven't allocated any memory to modify - you would attempt to modify a string literal "...", which would have been a bug. If you were to modify the strings, you should have declared them as arrays in main(): char mnemonic[] = "add";
Now as it turns out, whenever you use an array like the one in my example inside an expression, it "decays" into a pointer to the first element. So we wouldn't actually be able to pass the array by value to the function, as the C language would have changed it between the lines to a pointer to the first element.
You can play around with this code:
#include <stdio.h>
#include <string.h>
void analyse_inst(char* mnemonic, char* operands);
int main()
{
char mnemonic[] = "add";
char operands[] = "five to two";
analyse_inst(mnemonic, operands);
printf("%s\n", mnemonic);
}
void analyse_inst(char* mnemonic, char* operands)
{
printf("%s ", mnemonic);
printf("%s\n", operands);
strcpy(mnemonic, "hi");
}
When you write something like char *mnemonic that means you are creating a pointer variable (variable that will hold the address of another variable) but since the data type of the mnemonic is char it will hold the address of variable with char datatype only.
Now, inside your code you have written mnemonic = "add" so here "add" is the string that is array of characters and mnemonic is pointing to the base address of that array.
and while calling the function you are passing the references of these char arrays, so you need to change void analyse_inst(char mnemonic, char operands) to void analyse_inst(char *mnemonic, char *operands) to get the references in these respective pointer variables. Reason is same We need pointer variables to hold the references.
And the & returns the address of the variable, that means the reference to the memory location in which the variable is stored.
Hope this will help.
Strings in C are stored as arrays of characters, terminated by a character with the value '\0' ("NIL"). You cannot directly pass around arrays, so instead a pointer to the first character is used, which is why you must pass char *s to the function in order to access strings.
A character is typically much smaller than a pointer (think 8 vs 32/64 bits), so you cannot squeeze a pointer value into a single character.
C does not have pass by reference; it's pass by value only. Sometimes that value is as close to a reference as the language can come (i.e. a pointer), but then that pointer is in turn passed by value.
Consider this:
static void put_next(const char *s)
{
putchar(*s++);
}
int main(void)
{
const char *string = "hello";
put_next(string);
put_next(string);
}
This will print hh, since it's being passed the same value string every time, the fact that s, which is a different variable holding a copy of the same value, is incremented inside the function doesn't matter. The incremented value is local to the function, and thrown away once it goes out of scope.
I will discuss things in the context of your code, but I want to get some basics out of the way first.
In a declaration, the unary * operator indicates that the thing being declared has pointer type:
T *p; // for any type T, p has type "pointer to T"
T *p[N]; // for any type T, p has type "N-element array of pointer to T"
T (*p)[N]; // for any type T, p has type "pointer to N-element array of T"
T *f(); // for any type T, f has type "function returning pointer to T"
T (*f)(); // for any type T, f has type "pointer to function returning T"
The unary * operator has lower precedence then the postfix [] subscript and () function operators, so if you want a pointer to an array or a function, the * must be explicitly grouped with the identifier.
In an expression, the unary * operator dereferences the pointer, allowing us to access the pointed-to object or function:
int x;
int *p;
p = &x; // assign the address of x to p
*p = 10; // assigns 10 to x via p - int = int
After the above code has executed, the following are true:
p == &x // int * == int *
*p == x == 10 // int == int == int
The expressions p and &x have type int * (pointer to int), and their value is the (virtual) address of x. The expressions *p and x have type int, and their value is 10.
A valid1 object pointer value is obtained in one of three ways (function pointers are also a thing, but we won't get into them here):
using the unary & operator on an lvalue2 (p = &x;);
allocating dynamic memory via malloc(), calloc(), or realloc();
and, what is relevant for your code, using an array expression without a & or sizeof operator.
Except when it is the operand of the sizeof or unary & operator, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T" is converted ("decays") to an expression of type "pointer to T", and the value of the expression is the address of the first element of the array3. So, if you create an array like
int a[10];
and pass that array expression as an argument to a function like
foo( a );
then before the function is called, the expression a is converted from type "10-element array of int" to "pointer to int", and the value of a is the address of a[0]. So what the function actually receives is a pointer value, not an array:
void foo( int *a ) { ... }
String literals like "add" and "five to two" are array expressions - "add" has type "4-element array of char" and "five to two" has type "12-element array of char" (an N-character string requires at least N+1 elements to store because of the string terminator).
In the statements
mnemonic = "add";
operands = "five to two";
neither string literal is the operand of the sizeof or unary & operators, and they're not being used to initialize a character array in a declaration, so both expressions are converted to type char * and their values are the addresses of the first element of each array. Both mnemonic and operands are declared as char *, so this is fine.
Since the types of mnemonic and operands are both char *, when you call
analyse_inst( mnemonic, operands );
the types of the function's formal arguments must also be char *:
void analyse_inst( char *mnemonic, char *operands )
{
...
}
As far as the "pass by reference" bit...
C passes all function arguments by value. That means the formal argument in the function definition is a different object in memory from the actual argument in the function call, and any changes made to the formal argument are not reflected in the actual argument. Suppose we write a swap function as:
int swap( int a, int b )
{
int tmp = a;
a = b;
b = tmp;
}
int main( void )
{
int x = 2;
int y = 3;
printf( "before swap: x = %d, y = %d\n", x, y );
swap( x, y );
printf( "after swap: x = %d, y = %d\n", x, y );
...
}
If you compile and run this code, you'll see that the values of x and y don't change after the call to swap - the changes to a and b had no effect on x and y, because they're different objects in memory.
In order for the swap function to work, we have to pass pointers to x and y:
void swap( int *a, int *b )
{
int tmp = *a;
*a = *b;
*b = tmp;
}
int main( void )
{
...
swap( &x, &y );
...
}
In this case, the expressions *a and *b in swap refer to the same objects as the expressions x and y in main, so the changes to *a and *b are reflected in x and y:
a == &x, b == &y
*a == x, *b == y
So, in general:
void foo( T *ptr ) // for any non-array type T
{
*ptr = new_value(); // write a new value to the object `ptr` points to
}
void bar( void )
{
T var;
foo( &var ); // write a new value to var
}
This is also true for pointer types - replace T with a pointer type P *, and we get the following:
void foo( P **ptr ) // for any non-array type T
{
*ptr = new_value(); // write a new value to the object `ptr` points to
}
void bar( void )
{
P *var;
foo( &var ); // write a new value to var
}
In this case, var stores a pointer value. If we want to write a new pointer value to var through foo, then we must still pass a pointer to var as the argument. Since var has type P *, then the expression &var has type P **.
A pointer value is valid if it points to an object within that object's lifetime.
An lvalue is an expression that refers to an object such that the object's value may be read or modified.
Believe it or not there is a good reason for this rule, but it means that array expressions lose their "array-ness" under most circumstances, leading to much confusion among people first learning the language.
I was learning pointers in C when I wrote the following code:
#include <stdio.h>
main()
{
char *p = 0;
*p = 'a';
printf("value in pointer p is %c\n", *p);
}
When I compiled the code, It was compiled successfully. Although, when I executed its out file, a runt-time error occurred: Segmentation Fault (core dumped)
I couldn't understand why that run-time error occurred. After all, the pointer p was pointing to character a, and thus the output should've been a.
Although, when I wrote the following code, it compiled and ran successfully:
#include <stdio.h>
main ()
{
char *p = 0;
char output = 'a';
p = &output;
printf("value which pointer p points is %c\n", *p);
}
Can someone explain me why the first program fails, while the second program runs successfully?
Your code invokes undefined behavior because you are dereferencing a NULL1 pointer. A pointer needs to point to valid memory, a simple way to achieve what you want is this
#include <stdio.h>
int // `main()' MUST return `int'
main(void)
{
char *pointer;
char value;
pointer = &value; // Now the pointer points to valid memory
*pointer = 'a';
printf("value in pointer p is %c\n", *pointer);
return 0;
}
1
6.3.2.3 Pointers
An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. 66) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
66)The macro NULL is defined in (and other headers) as a null pointer constant; see 7.19.
6.5.3.2 Address and indirection operators
Semantics
The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.102)
102)Thus, &*E is equivalent to E (even if E is a null pointer), and &(E1[E2]) to ((E1)+(E2)). It is always true that if E is a function designator or an lvalue that is a valid operand of the unary & operator, *&E is a function designator or an lvalue equal to E. If *P is an lvalue and T is the name of an object pointer type, *(T)P is an lvalue that has a type compatible with that to which T points.
Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime.
In the first example, you set p to 0, which on most implementations is the same as NULL. You then attempt to dereference that pointer (read/write the memory location that p points to), which leads to the core dump. p is not pointing to the character a. This *p = 'a' says "take the memory location that p points to and put a there".
In the second example, you're setting p to the address of output, so it points to a known memory location. Then when you dereference is, you're reading the value at the location where p points, i.e. output. This is valid usage.
A pointer is a "special" variables that store the address of another variables. Take a look at this program, I hope that it will help you clarifying what a pointer is and how to use it :
#include <stdio.h>
int main(void){
int x = 10, *pointer = 0;
pointer = &x;
printf("\nThe address of x : %p.\n", &x);
printf("\nThe address of the pointer : %p.\n", pointer);
printf("\nThe value of x : %d.\n", x);
*pointer += 10;
printf("\nThe value of x after we modifed it with the pointer : %d.\n\n", x);
return 0;
}
If you compile and give this program a run, this will be its output:
The address of x : 0xbf912108.
The address of the pointer : 0xbf912108.
The value of x : 10.
The value of x after we modifed it with the pointer : 20.
As you can clearly see the address of the pointer is the same of the variable itself. That's why when you modify a pointer (for example in my program I do *pointer += 10) it's actually modifying the variable.