Section 1 -- pointer rules, 1) pointers and pointees, 2) dereferencing, 3) pointer assignment, section 2 -- binky's code example, java version, c++ version, pascal version, section 3 -- study questions.
TABLE OF CONTENTS (HIDE)
C++ programming language, pointers, references and dynamic memory allocation.
Pointers, References and Dynamic Memory Allocation are the most powerful features in C/C++ language, which allows programmers to directly manipulate memory to efficiently manage the memory - the most critical and scarce resource in computer - for best performance . However, "pointer" is also the most complex and difficult feature in C/C++ language.
Pointers are extremely powerful because they allows you to access addresses and manipulate their contents. But they are also extremely complex to handle. Using them correctly, they could greatly improve the efficiency and performance. On the other hand, using them incorrectly could lead to many problems, from un-readable and un-maintainable codes, to infamous bugs such as memory leaks and buffer overflow, which may expose your system to hacking. Many new languages (such as Java and C#) remove pointer from their syntax to avoid the pitfalls of pointers, by providing automatic memory management.
Although you can write C/C++ programs without using pointers, however, it is difficult not to mention pointer in teaching C/C++ language. Pointer is probably not meant for novices and dummies.
A computer memory location has an address and holds a content . The address is a numerical number (often expressed in hexadecimal), which is hard for programmers to use directly. Typically, each address location holds 8-bit (i.e., 1-byte) of data. It is entirely up to the programmer to interpret the meaning of the data, such as integer, real number, characters or strings.
To ease the burden of programming using numerical address and programmer-interpreted data, early programming languages (such as C) introduce the concept of variables. A variable is a named location that can store a value of a particular type . Instead of numerical addresses, names (or identifiers) are attached to certain addresses. Also, types (such as int , double , char ) are associated with the contents for ease of interpretation of data.
Each address location typically hold 8-bit (i.e., 1-byte) of data. A 4-byte int value occupies 4 memory locations. A 32-bit system typically uses 32-bit addresses. To store a 32-bit address, 4 memory locations are required.
The following diagram illustrate the relationship between computers' memory address and content ; and variable's name , type and value used by the programmers.
Pointer Variables (or Pointers)
A pointer variable (or pointer in short) is basically the same as the other variables, which can store a piece of data. Unlike normal variable which stores a value (such as an int , a double , a char ), a pointer stores a memory address .
Pointers must be declared before they can be used, just like a normal variable. The syntax of declaring a pointer is to place a * in front of the name. A pointer is associated with a type (such as int and double ) too.
Take note that you need to place a * in front of each pointer variable, in other words, * applies only to the name that followed. The * in the declaration statement is not an operator, but indicates that the name followed is a pointer variable. For example,
Naming Convention of Pointers: Include a " p " or " ptr " as prefix or suffix , e.g., iPtr , numberPtr , pNumber , pStudent .
Initializing Pointers via the Address-Of Operator ( & )
When you declare a pointer variable, its content is not initialized. In other words, it contains an address of "somewhere", which is of course not a valid location. This is dangerous! You need to initialize a pointer by assigning it a valid address. This is normally done via the address-of operator ( & ).
The address-of operator ( & ) operates on a variable, and returns the address of the variable. For example, if number is an int variable, &number returns the address of the variable number .
You can use the address-of operator to get the address of a variable, and assign the address to a pointer variable. For example,
As illustrated, the int variable number , starting at address 0x22ccec , contains an int value 88 . The expression &number returns the address of the variable number , which is 0x22ccec . This address is then assigned to the pointer variable pNumber , as its initial value.
The address-of operator ( & ) can only be used on the RHS.
Indirection or Dereferencing Operator ( * )
The indirection operator (or dereferencing operator ) ( * ) operates on a pointer, and returns the value stored in the address kept in the pointer variable. For example, if pNumber is an int pointer, *pNumber returns the int value " pointed to " by pNumber .
Take note that pNumber stores a memory address location, whereas *pNumber refers to the value stored in the address kept in the pointer variable, or the value pointed to by the pointer.
As illustrated, a variable (such as number ) directly references a value, whereas a pointer indirectly references a value through the memory address it stores. Referencing a value indirectly via a pointer is called indirection or dereferencing .
The indirection operator ( * ) can be used in both the RHS ( temp = *pNumber ) and the LHS ( *pNumber = 99 ) of an assignment statement.
Take note that the symbol * has different meaning in a declaration statement and in an expression. When it is used in a declaration (e.g., int * pNumber ), it denotes that the name followed is a pointer variable. Whereas when it is used in a expression (e.g., *pNumber = 99 ; temp << *pNumber; ), it refers to the value pointed to by the pointer variable.
Pointer has a Type Too
A pointer is associated with a type (of the value it points to), which is specified during declaration. A pointer can only hold an address of the declared type; it cannot hold an address of a different type.
Notes: The address values that you get are unlikely to be the same as mine. The OS loads the program in available free memory locations, instead of fixed memory locations.
The following code fragment has a serious logical error!
The pointer iPtr was declared without initialization, i.e., it is pointing to "somewhere" which is of course an invalid memory location. The *iPtr = 55 corrupts the value of "somewhere"! You need to initialize a pointer by assigning it a valid address. Most of the compilers does not signal an error or a warning for uninitialized pointer?!
You can initialize a pointer to 0 or NULL , i.e., it points to nothing. It is called a null pointer . Dereferencing a null pointer ( *p ) causes an STATUS_ACCESS_VIOLATION exception.
Initialize a pointer to null during declaration is a good software engineering practice.
C++11 introduces a new keyword called nullptr to represent null pointer.
C++ added the so-called reference variables (or references in short). A reference is an alias , or an alternate name to an existing variable. For example, suppose you make peter a reference (alias) to paul , you can refer to the person as either peter or paul .
The main use of references is acting as function formal parameters to support pass-by-reference. In an reference variable is passed into a function, the function works on the original copy (instead of a clone copy in pass-by-value). Changes inside the function are reflected outside the function.
A reference is similar to a pointer. In many cases, a reference can be used as an alternative to pointer, in particular, for the function parameter.
References (or Aliases) ( & )
Recall that C/C++ use & to denote the address-of operator in an expression. C++ assigns an additional meaning to & in declaration to declare a reference variable.
The meaning of symbol & is different in an expression and in a declaration. When it is used in an expression, & denotes the address-of operator, which returns the address of a variable, e.g., if number is an int variable, &number returns the address of the variable number (this has been described in the above section).
Howeve, when & is used in a declaration (including function formal parameters ), it is part of the type identifier and is used to declare a reference variable (or reference or alias or alternate name ). It is used to provide another name , or another reference , or alias to an existing variable.
The syntax is as follow:
It shall be read as " newName is a reference to exisitngName ", or " newNew is an alias of existingName ". You can now refer to the variable as newName or existingName .
How References Work?
A reference works as a pointer. A reference is declared as an alias of a variable. It stores the address of the variable, as illustrated:
References vs. Pointers
Pointers and references are equivalent, except:
- A reference is a name constant for an address . You need to initialize the reference during declaration. int & iRef; // Error: 'iRef' declared as reference but not initialized Once a reference is established to a variable, you cannot change the reference to reference another variable.
- To get the value pointed to by a pointer, you need to use the dereferencing operator * (e.g., if pNumber is a int pointer, *pNumber returns the value pointed to by pNumber . It is called dereferencing or indirection ). To assign an address of a variable into a pointer, you need to use the address-of operator & (e.g., pNumber = &number ). On the other hand, referencing and dereferencing are done on the references implicitly. For example, if refNumber is a reference (alias) to another int variable, refNumber returns the value of the variable. No explicit dereferencing operator * should be used. Furthermore, to assign an address of a variable to a reference variable, no address-of operator & is needed.
A reference variable provides a new name to an existing variable. It is dereferenced implicitly and does not need the dereferencing operator * to retrieve the value referenced. On the other hand, a pointer variable stores an address. You can change the address value stored in a pointer. To retrieve the value pointed to by a pointer, you need to use the indirection operator * , which is known as explicit dereferencing . Reference can be treated as a const pointer. It has to be initialized during declaration, and its content cannot be changed.
Reference is closely related to pointer. In many cases, it can be used as an alternative to pointer. A reference allows you to manipulate an object using pointer, but without the pointer syntax of referencing and dereferencing.
The above example illustrates how reference works, but does not show its typical usage, which is used as the function formal parameter for pass-by-reference.
Pass-By-Reference into Functions with Reference Arguments vs. Pointer Arguments
In C/C++, by default, arguments are passed into functions by value (except arrays which is treated as pointers). That is, a clone copy of the argument is made and passed into the function. Changes to the clone copy inside the function has no effect to the original argument in the caller. In other words, the called function has no access to the variables in the caller. For example,
The output clearly shows that there are two different addresses.
Pass-by-Reference with Pointer Arguments
In many situations, we may wish to modify the original copy directly (especially in passing huge object or array) to avoid the overhead of cloning. This can be done by passing a pointer of the object into the function, known as pass-by-reference . For example,
The called function operates on the same address, and can thus modify the variable in the caller.
Pass-by-Reference with Reference Arguments
Instead of passing pointers into function, you could also pass references into function, to avoid the clumsy syntax of referencing and dereferencing. For example,
Again, the output shows that the called function operates on the same address, and can thus modify the caller's variable.
Take note referencing (in the caller) and dereferencing (in the function) are done implicitly. The only coding difference with pass-by-value is in the function's parameter declaration.
Recall that references are to be initialized during declaration. In the case of function formal parameter, the references are initialized when the function is invoked, to the caller's arguments.
References are primarily used in passing reference in/out of functions to allow the called function accesses variables in the caller directly.
" const " Function Reference/Pointer Parameters
A const function formal parameter cannot be modified inside the function. Use const whenever possible as it protects you from inadvertently modifying the parameter and protects you against many programming errors.
A const function parameter can receive both const and non- const argument. On the other hand, a non- const function reference/pointer parameter can only receive non- const argument. For example,
Passing the Function's Return Value
Passing the return-value as reference.
You can also pass the return-value as reference or pointer. For example,
You should not pass Function's local variable as return value by reference
This program has a serious logical error, as local variable of function is passed back as return value by reference. Local variable has local scope within the function, and its value is destroyed after the function exits. The GCC compiler is kind enough to issue a warning (but not error).
It is safe to return a reference that is passed into the function as an argument. See earlier examples.
Passing Dynamically Allocated Memory as Return Value by Reference
Instead, you need to dynamically allocate a variable for the return value, and return it by reference.
Pointers and references are highly complex and difficult to master. But they can greatly improve the efficiency of the programs.
For novices, avoid using pointers in your program. Improper usage can lead to serious logical bugs. However, you need to understand the syntaxes of pass-by-reference with pointers and references, because they are used in many library functions.
- In pass-by-value , a clone is made and passed into the function. The caller's copy cannot be modified.
- In pass-by-reference , a pointer is passed into the function. The caller's copy could be modified inside the function.
- In pass-by-reference with reference arguments , you use the variable name as the argument.
- In pass-by-reference with pointer arguments , you need to use & varName (an address) as the argument.
Dynamic Memory Allocation
New and delete operators.
Instead of define an int variable ( int number ), and assign the address of the variable to the int pointer ( int *pNumber = &number ), the storage can be dynamically allocated at runtime, via a new operator. In C++, whenever you allocate a piece of memory dynamically via new , you need to use delete to remove the storage (i.e., to return the storage to the heap).
The new operation returns a pointer to the memory allocated. The delete operator takes a pointer (pointing to the memory allocated via new ) as its sole argument.
Observe that new and delete operators work on pointer .
To initialize the allocated memory, you can use an initializer for fundamental types, or invoke a constructor for an object. For example,
You can dynamically allocate storage for global pointers inside a function. Dynamically allocated storage inside the function remains even after the function exits. For example,
The main differences between static allocation and dynamic allocations are:
- In static allocation, the compiler allocates and deallocates the storage automatically, and handle memory management. Whereas in dynamic allocation, you, as the programmer, handle the memory allocation and deallocation yourself (via new and delete operators). You have full control on the pointer addresses and their contents, as well as memory management.
- Static allocated entities are manipulated through named variables. Dynamic allocated entities are handled through pointers.
new and delete Operators
Dynamic array is allocated at runtime rather than compile-time, via the new operator. To remove the storage, you need to use the delete operator (instead of simply delete ). For example,
C++03 does not allow your to initialize the dynamically-allocated array. C++11 does with the brace initialization, as follows:
Pointer, Array and Function
Array is treated as pointer.
In C/C++, an array's name is a pointer, pointing to the first element (index 0) of the array. For example, suppose that numbers is an int array, numbers is a also an int pointer, pointing at the first element of the array. That is, numbers is the same as &numbers . Consequently, *numbers is number ; *(numbers+i) is numbers[i] .
As seen from the previous section, if numbers is an int array, it is treated as an int pointer pointing to the first element of the array. (numbers + 1) points to the next int , instead of having the next sequential address. Take note that an int typically has 4 bytes. That is (numbers + 1) increases the address by 4, or sizeof(int) . For example,
The operation sizeof( arrayName ) returns the total bytes of the array. You can derive the length (size) of the array by dividing it with the size of an element (e.g. element 0). For example,
Passing Array In/Out of a Function
An array is passed into a function as a pointer to the first element of the array. You can use array notation (e.g., int ) or pointer notation (e.g., int* ) in the function declaration. The compiler always treats it as pointer (e.g., int* ). For example, the following declarations are equivalent:
They will be treated as int* by the compiler, as follow. The size of the array given in  is ignored.
Array is passed by reference into the function, because a pointer is passed instead of a clone copy. If the array is modified inside the function, the modifications are applied to the caller's copy. You could declare the array parameter as const to prevent the array from being modified inside the function.
The size of the array is not part of the array parameter, and needs to be passed in another int parameter. Compiler is not able to deduce the array size from the array pointer, and does not perform array bound check.
Example: Using the usual array notation.
Take note that you can modify the contents of the caller's array inside the function, as array is passed by reference. To prevent accidental modification, you could apply const qualifier to the function's parameter. Recall that const inform the compiler that the value should not be changed. For example, suppose that the function print() prints the contents of the given array and does not modify the array, you could apply const to both the array name and its size, as they are not expected to be changed inside the function.
Compiler flags out an error "assignment of read-only location" if it detected a const value would be changed.
Example: Using pointer notation.
Pass-by-Reference and sizeof
The address of arrays in main() and the function are the same, as expected, as array is passed by reference.
In main() , the sizeof array is 20 (4 bytes per int , length of 5). Inside the function, the sizeof is 4, which is the sizeof int pointer (4-byte address). This is why you need to pass the size into the function.
Operating on a Range of an Array
- To write a function that operates on a range of the given array, you can pass the begin pointer and the end pointer into the function. By convention, the operation shall start at the begin pointer, up to the end pointer, but excluding the end pointer.
- In " const int *p ", *p (content pointed-to) is constant, but p is not constant.
C-String and Pointer
C-string (of the C language) is a character array, terminated with a null character '\0' . For example,
Take note that for C-String function such as strlen() (in header cstring , ported over from C's string.h ), there is no need to pass the array length into the function. This is because C-Strings are terminated by '\0' . The function can iterate thru the characters in the array until '\0' . For example,
* More On Pointers
In C/C++, functions, like all data items, have an address. The name of a function is the starting address where the function resides in the memory, and therefore, can be treated as a pointer. We can pass a function pointer into function as well. The syntax for declaring a function pointer is:
Generic Pointer or void Pointer ( void * )
A void pointer can hold address of any data type (except function pointer). We cannot operate on the object pointed to by void pointer, as the type is unknown. We can use a void pointer to compare with another address.
Constant Pointer vs. Constant Pointed-to Data
- Non-constant pointer to constant data: Data pointed to CANNOT be changed; but pointer CAN be changed to point to another data. For example, int i1 = 8, i2 = 9; const int * iptr = &i1; // non-constant pointer pointing to constant data // *iptr = 9; // error: assignment of read-only location iptr = &i2; // okay
- Constant pointer to non-constant data: Data pointed to CAN be changed; but pointer CANNOT be changed to point to another data. For example, int i1 = 8, i2 = 9; int * const iptr = &i1; // constant pointer pointing to non-constant data // constant pointer must be initialized during declaration *iptr = 9; // okay // iptr = &i2; // error: assignment of read-only variable
- Constant pointer to constant data: Data pointed to CANNOT be changed; and pointer CANNOT be changed to point to another data. For example, int i1 = 8, i2 = 9; const int * const iptr = &i1; // constant pointer pointing to constant data // *iptr = 9; // error: assignment of read-only variable // iptr = &i2; // error: assignment of read-only variable
- Non-constant pointer to non-constant data: Data pointed to CAN be changed; and pointer CAN be changed to point to another data. For example, int i1 = 8, i2 = 9; int * iptr = &i1; // non-constant pointer pointing to non-constant data *iptr = 9; // okay iptr = &i2; // okay
Latest version tested: Cygwin/MinGW GCC 4.6.2 Last modified: April, 2013
[This section corresponds to K&R Sec. 5.1]
The first things to do with 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; This declaration looks like our earlier declarations, with one obvious difference: that asterisk. The asterisk means that ip , the variable we're declaring, is not of type int , but rather of type pointer-to- int . (Another way of looking at it is that *ip , which as we'll see is the value pointed to by ip , will be an int .)
We may think of setting a pointer variable to point to another variable as a two-step process: first we generate a pointer to that other variable, then we assign this new pointer to the pointer variable. We can say (but we have to be careful when we're saying it) that a pointer variable has a value, and that its value is ``pointer to that other variable''. This will make more sense when we see how to generate pointer values.
We discover the value pointed to by a pointer using the ``contents-of'' operator, * . Placed in front of a pointer, the * operator accesses the value pointed to by that pointer. In other words, if ip is a pointer, then the expression *ip gives us whatever it is that's in the variable or location pointed to by ip . For example, we could write something like printf("%d\n", *ip); which would print 5, since ip points to i , and i is (at the moment) 5.
(You may wonder how the asterisk * can be the pointer contents-of operator when it is also the multiplication operator. There is no ambiguity here: it is the multiplication operator when it sits between two variables, and it is the contents-of operator when it sits in front of a single variable. The situation is analogous to the minus sign: between two variables or expressions it's the subtraction operator, but in front of a single variable or expression it's the negation operator. Technical terms you may hear for these distinct roles are unary and binary : a binary operator applies to two operands, usually on either side of it, while a unary operator applies to a single operand.)
The contents-of operator * does not merely fetch values through pointers; it can also set values through pointers. We can write something like *ip = 7; which means ``set whatever ip points to to 7.'' Again, the * tells us to go to the location pointed to by ip , but this time, the location isn't the one to fetch from--we're on the left-hand side of an assignment operator, so *ip tells us the location to store to . (The situation is no different from array subscripting expressions such as a which we've already seen appearing on both sides of assignments.)
We can now see that the two assignments ip2 = ip; and *ip2 = *ip; do two very different things. The first would make ip2 again point to where ip points (in other words, back to i again). The second would store, at the location pointed to by ip2 , a copy of the value pointed to by ip ; in other words (if ip and ip2 still point to i and j respectively) it would set j to i 's value, or 7.
It's important to keep very clear in your mind the distinction between a pointer and what it points to . The two are like apples and oranges (or perhaps oil and water); you can't mix them. You can't ``set ip to 5'' by writing something like ip = 5; /* WRONG */ 5 is an integer, but ip is a pointer. You probably wanted to ``set the value pointed to by ip to 5,'' which you express by writing *ip = 5; Similarly, you can't ``see what ip is'' by writing printf("%d\n", ip); /* WRONG */ Again, ip is a pointer-to- int , but %d expects an int . To print what ip points to , use printf("%d\n", *ip);
Finally, a few more notes about pointer declarations. The * in a pointer declaration is related to, but different from, the contents-of operator * . After we declare a pointer variable int *ip; the expression ip = &i sets what ip points to (that is, which location it points to), while the expression *ip = 5 sets the value of the location pointed to by ip . On the other hand, if we declare a pointer variable and include an initializer: int *ip3 = &i; we're setting the initial value for ip3 , which is where ip3 will point, so that initial value is a pointer. (In other words, the * in the declaration int *ip3 = &i; is not the contents-of operator, it's the indicator that ip3 is a pointer.)
If you have a pointer declaration containing an initialization, and you ever have occasion to break it up into a simple declaration and a conventional assignment, do it like this: int *ip3; ip3 = &i; Don't write int *ip3; *ip3 = &i; or you'll be trying to mix oil and water again.
Also, when we write int *ip; although the asterisk affects ip 's type, it goes with the identifier name ip , not with the type int on the left. To declare two pointers at once, the declaration looks like int *ip1, *ip2; Some people write pointer declarations like this: int* ip; This works for one pointer, because C essentially ignores whitespace. But if you ever write int* ip1, ip2; /* PROBABLY WRONG */ it will declare one pointer-to- int ip1 and one plain int ip2 , which is probably not what you meant.
What is all of this good for? If it was just for changing variables like i from 5 to 7, it would not be good for much. What it's good for, among other things, is when for various reasons we don't know exactly which variable we want to change, just like the bank didn't know exactly which club member it wanted to send the statement to.
Read sequentially: prev next up top
This page by Steve Summit // Copyright 1995, 1996 // mail feedback
- Skip to main content
- Skip to primary sidebar
- Skip to secondary sidebar
- Skip to footer
- Computer Fundamental
- Computer Memory
- DBMS Tutorial
- Operating System
- Computer Networking
- C Programming
- C++ Programming
- Java Programming
- C# Programming
- SQL Tutorial
- Management Tutorial
- Computer Graphics
- Compiler Design
- Style Sheet
- Html Tutorial
- Wordpress Tutorial
- Python Tutorial
- PHP Tutorial
- JSP Tutorial
- AngularJS Tutorial
- Data Structures
- E Commerce Tutorial
- Visual Basic
- Structs2 Tutorial
- Digital Electronics
- Internet Terms
- Servlet Tutorial
- Software Engineering
- Interviews Questions
- Basic Terms
How to pointer assignment and initialization in c.
By Dinesh Thakur
When we declare a pointer, it does not point to any specific variable. We must initialize it to point to the desired variable. This is achieved by assigning the address of that variable to the pointer variable, as shown below.
int a = 10;
pa = &a; /* pointer variable pa now points to variable a */
In this example, the first line declares an int variable named a and initializes it to 10. The second line declares a pointer pa of type pointer to int. Finally, the address of variable a is assigned to pa.Now pa is said to point to variable a.
We can also initialize a pointer when it is declared using the format given below.
type * ptr_var = init_expr ;
where init_expr is an expression that specifies the address of a previously defined variable of appropriate type or it can be NULL, a constant defined in the <stdio.h> header file.
Consider the example given below.
float x = 0.5;
float *px = &x;
int *p = NULL;
The second line declares a pointer variable px of type float * and initializes it with the address of variable x declared in the first line. Thus, pointer px now points to variable x. The third line declares pointer variable p of type int * and initializes it to NULL. Thus, pointer p does not point to any variable and it is an error to dereference such a pointer.
Note that a character pointer can be initialized using a character string constant as in
char *msg = “Hello, world!”;
Here, the C compiler allocates the required memory for the string constant (14 characters, in the above example, including the null terminator), stores the string constant in this memory and then assigns the initial address of this memory to pointer msg,as iliustrated in Fig.
The C language also permits initialization of more that one pointer variable in a single statement using the format shown below.
type *ptr_var1 = init_expr1, *ptr_var2 = init_expr2, … ;
It is also possible to mix the declaration and initialization of ordinary variables and pointers. However, we should avoid it to maintain program readability.
Example of Pointer Assignment and Initialization
char a= ‘A’;
char *pa = &a;
printf(“The address of character variable a: %p\n”, pa);
printf(“The address of pointer variable pa : %p\n”, &pa);
printf(“The value pointed by pointer variable pa: %c\n”, *pa);
Here, pa is a character pointer variable that is initialized with the address of character variable a defined in the first line. Thus, pa points to variable a. The first two printf statements print the address of variables a and pa using the %p (p for pointer) conversion. The last printf statement prints the value of a using the pointer variable pa. When the program containing this code is executed in Code::Blocks, the output is displayed as shown below. ·
The address of character variable a: 0022FF1F
The address of pointer variable pa : 0022FF18
The value pointed by pointer variable pa: A
Note that the addresses displayed in the output will usually be different depending on other variables declared in the program and the compiler/IDE used.
Another example is given below in which pointers are initialized with the addresses of variables of incompatible type.
char c = ‘Z’;
int i = 10;
float f = 1.1;
char *pcl = &i, *pc2 = &f;
int *pil = &c, *pi2 = &f;
float *pfl = &c, *pf2 = &i;
printf(“Character: %c %c\n”, *pcl, *pc2);
printf(“Integer : %d %d\n”, *pil, *pi2);
printf (“Float : %f %f\n”, =pfl, *pf2);
Note that the character pointer variables pcl and pc2 are initialized with the addresses of the int and float variables, respectively. Similarly, the int and float pointer variables are also initialized with addresses of variables of incompatible type. When the program containing this code is compiled in Code::Blocks, the compiler reports six warning messages (initialization from incompatible pointer type), one for each incompatible pointer initialization.
It is not a good idea to ignore such warnings associated with pointers. Although, the program executes in the presence of these warnings, it displays wrong results as shown below.
Integer : 90 1066192077
Float : 0.000000 0.000000
You’ll also like:
- Write A C++ Program To Signify Importance Of Assignment (=) And Shorthand Assignment (+=) Operator.
- Write C++ Example to illustrate two dimensional array implemented as pointer to a pointer.
- Two-Dimensional Arrays Using a Pointer to Pointer
- Declaration and Initialization of Pointers in C
- Initialization of Two Dimensional Arrays Java
Dinesh Thakur is a Freelance Writer who helps different clients from all over the globe. Dinesh has written over 500+ blogs, 30+ eBooks, and 10000+ Posts for all types of clients.
For any type of query or something that you think is missing, please feel free to Contact us .
- Database System
- Management System
- Electronic Commerce
- Structured Query (SQL)
- Java Servlet
World Wide Web
- Java Script
- HTML Language
- Cascading Style Sheet
- Java Server Pages
Something went wrong. Wait a moment and try again.
- Latest Articles
- Top Articles
- Posting/Update Guidelines
- Article Help Forum
- View Unanswered Questions
- View All Questions
- View C# questions
- View C++ questions
- View Python questions
- View Java questions
- CodeProject.AI Server
- All Message Boards...
- Running a Business
- Sales / Marketing
- Collaboration / Beta Testing
- Work Issues
- Design and Architecture
- Artificial Intelligence
- Internet of Things
- ATL / WTL / STL
- Managed C++/CLI
- Objective-C and Swift
- System Admin
- Hosting and Servers
- Linux Programming
- .NET (Core and Framework)
- Visual Basic
- Web Development
- Site Bugs / Suggestions
- Spam and Abuse Watch
- The Insider Newsletter
- The Daily Build Newsletter
- Newsletter archive
- CodeProject Stuff
- Most Valuable Professionals
- The Lounge
- The CodeProject Blog
- Where I Am: Member Photos
- The Insider News
- The Weird & The Wonderful
- What is 'CodeProject'?
- General FAQ
- Ask a Question
- Bugs and Suggestions
Assign new value to pointer in C
- Most Recent
Add your solution here
- Read the question carefully.
- Understand that English isn't everyone's first language so be lenient of bad spelling and grammar.
- If a question is poorly phrased then either ask for clarification, ignore it, or edit the question and fix the problem. Insults are not welcome.
This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)
C Programming/Pointers and arrays
A pointer is a value that designates the address (i.e., the location in memory), of some value. Pointers are variables that hold a memory location.
There are four fundamental things you need to know about pointers:
- How to declare them (with the address operator ' & ': int *pointer = &variable; )
- How to assign to them ( pointer = NULL; )
- How to reference the value to which the pointer points (known as dereferencing , by using the dereferencing operator ' * ': value = *pointer; )
- How they relate to arrays (the vast majority of arrays in C are simple lists, also called "1 dimensional arrays", but we will briefly cover multi-dimensional arrays with some pointers in a later chapter ).
Pointers can reference any data type, even functions. We'll also discuss the relationship of pointers with text strings and the more advanced concept of function pointers.
- 1 Declaring pointers
- 2 Assigning values to pointers
- 3 Pointer dereferencing
- 4 Pointers and Arrays
- 5 Pointers in Function Arguments
- 6 Pointers and Text Strings
- 7.1 Practical use of function pointers in C
- 8 Examples of pointer constructs
- 10 External Links
Declaring pointers [ edit | edit source ]
Consider the following snippet of code which declares two pointers:
Lines 1-4 define a structure . Line 8 declares a variable that points to an int , and line 9 declares a variable that points to something with structure MyStruct. So to declare a variable as something that points to some type, rather than contains some type, the asterisk ( * ) is placed before the variable name.
In the following, line 1 declares var1 as a pointer to a long and var2 as a long and not a pointer to a long. In line 2, p3 is declared as a pointer to a pointer to an int.
Pointer types are often used as parameters to function calls. The following shows how to declare a function which uses a pointer as an argument. Since C passes function arguments by value, in order to allow a function to modify a value from the calling routine, a pointer to the value must be passed. Pointers to structures are also used as function arguments even when nothing in the struct will be modified in the function. This is done to avoid copying the complete contents of the structure onto the stack. More about pointers as function arguments later.
Assigning values to pointers [ edit | edit source ]
So far we've discussed how to declare pointers. The process of assigning values to pointers is next. To assign the address of a variable to a pointer, the & or 'address of' operator is used.
Here, pPointer will now reference myInt and pKeyboard will reference dvorak.
Pointers can also be assigned to reference dynamically allocated memory. The malloc() and calloc() functions are often used to do this.
The malloc function returns a pointer to dynamically allocated memory (or NULL if unsuccessful). The size of this memory will be appropriately sized to contain the MyStruct structure.
The following is an example showing one pointer being assigned to another and of a pointer being assigned a return value from a function.
When returning a pointer from a function, do not return a pointer that points to a value that is local to the function or that is a pointer to a function argument. Pointers to local variables become invalid when the function exits. In the above function, the value returned points to a static variable. Returning a pointer to dynamically allocated memory is also valid.
Pointer dereferencing [ edit | edit source ]
To access a value to which a pointer points, the * operator is used. Another operator, the -> operator is used in conjunction with pointers to structures. Here's a short example.
The expression bb->m_aNumber is entirely equivalent to (*bb).m_aNumber . They both access the m_aNumber element of the structure pointed to by bb . There is one more way of dereferencing a pointer, which will be discussed in the following section.
When dereferencing a pointer that points to an invalid memory location, an error often occurs which results in the program terminating. The error is often reported as a segmentation error. A common cause of this is failure to initialize a pointer before trying to dereference it.
C is known for giving you just enough rope to hang yourself, and pointer dereferencing is a prime example. You are quite free to write code that accesses memory outside that which you have explicitly requested from the system. And many times, that memory may appear as available to your program due to the vagaries of system memory allocation. However, even if 99 executions allow your program to run without fault, that 100th execution may be the time when your "memory pilfering" is caught by the system and the program fails. Be careful to ensure that your pointer offsets are within the bounds of allocated memory!
The declaration void *somePointer; is used to declare a pointer of some nonspecified type. You can assign a value to a void pointer, but you must cast the variable to point to some specified type before you can dereference it. Pointer arithmetic is also not valid with void * pointers.
Pointers and Arrays [ edit | edit source ]
Up to now, we've carefully been avoiding discussing arrays in the context of pointers. The interaction of pointers and arrays can be confusing but here are two fundamental statements about it:
- A variable declared as an array of some type acts as a pointer to that type. When used by itself, it points to the first element of the array.
- A pointer can be indexed like an array name.
The first case often is seen to occur when an array is passed as an argument to a function. The function declares the parameter as a pointer, but the actual argument may be the name of an array. The second case often occurs when accessing dynamically allocated memory.
Let's look at examples of each. In the following code, the call to calloc() effectively allocates an array of struct MyStruct items.
Pointers and array names can pretty much be used interchangeably; however, there are exceptions. You cannot assign a new pointer value to an array name. The array name will always point to the first element of the array. In the function returnSameIfAnyEquals , you could however assign a new value to workingArray, as it is just a pointer to the first element of workingArray. It is also valid for a function to return a pointer to one of the array elements from an array passed as an argument to a function. A function should never return a pointer to a local variable, even though the compiler will probably not complain.
When declaring parameters to functions, declaring an array variable without a size is equivalent to declaring a pointer. Often this is done to emphasize the fact that the pointer variable will be used in a manner equivalent to an array.
Now we're ready to discuss pointer arithmetic. You can add and subtract integer values to/from pointers. If myArray is declared to be some type of array, the expression *(myArray+j) , where j is an integer, is equivalent to myArray[j] . For instance, in the above example where we had the expression secondArray[i].otherNumber , we could have written that as (*(secondArray+i)).otherNumber or more simply (secondArray+i)->otherNumber .
Note that for addition and subtraction of integers and pointers, the value of the pointer is not adjusted by the integer amount, but is adjusted by the amount multiplied by the size of the type to which the pointer refers in bytes. (For example, pointer + x can be thought of as pointer + (x * sizeof(*type)) .)
One pointer may also be subtracted from another, provided they point to elements of the same array (or the position just beyond the end of the array). If you have a pointer that points to an element of an array, the index of the element is the result when the array name is subtracted from the pointer. Here's an example.
You may be wondering how pointers and multidimensional arrays interact. Let's look at this a bit in detail. Suppose A is declared as a two dimensional array of floats ( float A[D1][D2]; ) and that pf is declared a pointer to a float. If pf is initialized to point to A, then *(pf+1) is equivalent to A and *(pf+D2) is equivalent to A. The elements of the array are stored in row-major order.
Let's look at a slightly different problem. We want to have a two dimensional array, but we don't need to have all the rows the same length. What we do is declare an array of pointers. The second line below declares A as an array of pointers. Each pointer points to a float. Here's some applicable code:
We also note here something curious about array indexing. Suppose myArray is an array and i is an integer value. The expression myArray[i] is equivalent to i[myArray] . The first is equivalent to *(myArray+i) , and the second is equivalent to *(i+myArray) . These turn out to be the same, since the addition is commutative.
Pointers can be used with pre-increment or post-decrement, which is sometimes done within a loop, as in the following example. The increment and decrement applies to the pointer, not to the object to which the pointer refers. In other words, *pArray++ is equivalent to *(pArray++) .
Pointers in Function Arguments [ edit | edit source ]
Often we need to invoke a function with an argument that is itself a pointer. In many instances, the variable is itself a parameter for the current function and may be a pointer to some type of structure. The ampersand ( & ) character is not needed in this circumstance to obtain a pointer value, as the variable is itself a pointer. In the example below, the variable pStruct , a pointer, is a parameter to function FunctTwo , and is passed as an argument to FunctOne .
The second parameter to FunctOne is an int. Since in function FunctTwo , mValue is a pointer to an int, the pointer must first be dereferenced using the * operator, hence the second argument in the call is *mValue . The third parameter to function FunctOne is a pointer to a long. Since pAA is itself a pointer to a long, no ampersand is needed when it is used as the third argument to the function.
Pointers and Text Strings [ edit | edit source ]
Historically, text strings in C have been implemented as arrays of characters, with the last byte in the string being a zero, or the null character '\0'. Most C implementations come with a standard library of functions for manipulating strings. Many of the more commonly used functions expect the strings to be null terminated strings of characters. To use these functions requires the inclusion of the standard C header file "string.h".
A statically declared, initialized string would look similar to the following:
The variable myFormat can be viewed as an array of 21 characters. There is an implied null character ('\0') tacked on to the end of the string after the 'd' as the 21st item in the array. You can also initialize the individual characters of the array as follows:
An initialized array of strings would typically be done as follows:
The initialization of an especially long string can be split across lines of source code as follows.
The library functions that are used with strings are discussed in a later chapter.
Pointers to Functions [ edit | edit source ]
C also allows you to create pointers to functions. Pointers to functions syntax can get rather messy. As an example of this, consider the following functions:
Declaring a typedef to a function pointer generally clarifies the code. Here's an example that uses a function pointer, and a void * pointer to implement what's known as a callback. The DoSomethingNice function invokes a caller supplied function TalkJive with caller data. Note that DoSomethingNice really doesn't know anything about what dataPointer refers to.
Some versions of C may not require an ampersand preceding the TalkJive argument in the DoSomethingNice call. Some implementations may require specifically casting the argument to the MyFunctionType type, even though the function signature exacly matches that of the typedef.
Function pointers can be useful for implementing a form of polymorphism in C. First one declares a structure having as elements function pointers for the various operations to that can be specified polymorphically. A second base object structure containing a pointer to the previous structure is also declared. A class is defined by extending the second structure with the data specific for the class, and static variable of the type of the first structure, containing the addresses of the functions that are associated with the class. This type of polymorphism is used in the standard library when file I/O functions are called.
A similar mechanism can also be used for implementing a state machine in C. A structure is defined which contains function pointers for handling events that may occur within state, and for functions to be invoked upon entry to and exit from the state. An instance of this structure corresponds to a state. Each state is initialized with pointers to functions appropriate for the state. The current state of the state machine is in effect a pointer to one of these states. Changing the value of the current state pointer effectively changes the current state. When some event occurs, the appropriate function is called through a function pointer in the current state.
Practical use of function pointers in C [ edit | edit source ]
Function pointers are mainly used to reduce the complexity of switch statement. Example with switch statement:
Without using a switch statement:
Function pointers may be used to create a struct member function:
Use to implement this pointer (following code must be placed in library).
Examples of pointer constructs [ edit | edit source ]
Below are some example constructs which may aid in creating your pointer.
sizeof [ edit | edit source ]
The sizeof operator is often used to refer to the size of a static array declared earlier in the same function.
To find the end of an array (example from wikipedia:Buffer overflow ):
To iterate over every element of an array, use
Note that the sizeof operator only works on things defined earlier in the same function. The compiler replaces it with some fixed constant number. In this case, the buffer was declared as an array of 10 char's earlier in the same function, and the compiler replaces sizeof(buffer) with the number 10 at compile time (equivalent to us hard-coding 10 into the code in place of sizeof(buffer) ). The information about the length of buffer is not actually stored anywhere in memory (unless we keep track of it separately) and cannot be programmatically obtained at run time from the array/pointer itself.
Often a function needs to know the size of an array it was given -- an array defined in some other function. For example,
Unfortunately, (in C and C++) the length of the array cannot be obtained from an array passed in at run time, because (as mentioned above) the size of an array is not stored anywhere. The compiler always replaces sizeof with a constant. This sum() routine needs to handle more than just one constant length of an array.
There are some common ways to work around this fact:
- Write the function to require, for each array parameter, a "length" parameter (which has type "size_t"). (Typically we use sizeof at the point where this function is called).
- Use of a convention, such as a null-terminated string to mark the end of the array.
- Instead of passing raw arrays, pass a structure that includes the length of the array (such as ".length") as well as the array (or a pointer to the first element); similar to the string or vector classes in C++.
It's worth mentioning that sizeof operator has two variations: sizeof ( type ) (for instance: sizeof (int) or sizeof (struct some_structure) ) and sizeof expression (for instance: sizeof some_variable.some_field or sizeof 1 ).
External Links [ edit | edit source ]
- "Common Pointer Pitfalls" by Dave Marshall
- Book:C Programming