Vous êtes sur la page 1sur 39

Fundamentals Of Programming in C

Presented By: Saket Kr Pathak M.Sc. NT & M Fundamental Of Programming in C

Pointers:
Pointers are easy to go like smooth way where programmer's doesnt need to apply force for running, they just fly in the space of zero gravity and got a lot new things as concept which can be implemented and makes their dream true. Pointers are just variables simple as other built-in data types int, float, char etc. but the special character stick makes it noticeable is, it will store only the address of another variable of concern type. Declaration: int _iNam = 3; int *_iPtr; _iPtr = &_iNam; We will discuss, the above statements in the following description.

In the above statements, first statement is just the declaration as well as initialization of the integral type variable named as _iNam. Where as in the 2nd statement, we are just declaring the integral type pointer variable named as _iPtr. At the 3rd statement, the pointer variable initialized with the memory address of the integral variable _iPtr. Structure of Pointer variable:
_iNam
Variable Name Value Stored Memory Location Pointer Variable Name Address Stored Memory Location

_iPtr

3
2004

2004
8004

So according to the above explanation and concerned the structural pattern followed, we can conclude that the integral variable named as _iNam has the value stored is 3 having a memory location say 2004. Where as the pointer variable named _iPtr has the value stored is the memory address of the integral variable _iNam and has another memory location say 8004. Now let us print these variables as value and their memory location through the syntactical support of programming language C. Code Snippet:
printf(Memo. Loc. Of _iNam = %u as Value = %d, &_iNam, _iNam); printf(Memo. Loc. Of *_iPtr = %u,&_iPtr); printf(Value stored in *_iPtr = %u,_iPtr); printf(Value pointing through *_iPtr = %d,*_iPtr);

Following we have the explanation of all these above statements.


4

In the very first statement the printf() function is displaying the message with the supported identifiers as %u and %d. Here %u is used for indicating the variables memory location, because the memory location will always be in unsigned integer type and is represented through addressof operator with variable name. The 2nd identifier is %d which indicates the integral value stored in the Memory location allocated to the variable _iNam. In the 2nd statement, which is quite straight forward and says, I will display the memory location allocated to the pointer variable named as _iPtr. Same as above the identifier used here to display memo. loc. is %u which indicates unsigned integral value and same represented through addressof operator with variable name.

In the 3rd statement, the value stored in the memo. loc. allocated to the pointer variable comes to the screen. The value stored in the memo. loc. of the pointer variable is just the memory address of the integral value. In the last statement said as 4th statement the actual pointer value i.e. the value to which the pointer variable points to is to be displayed. The operator as * (called as asterisk) is used to display the value stored to the specified location by pointer. Hence form the above discussion we have a clear picture of pointer and pointer variables supported by the syntax of C. Lets have a screen shot of these statement in the following.

Memory Location

Here in the above screen shot the memory value is in 32-bit mode hence integer type has quite large range. This output is the product of DevC++ compiler and has 32-bit structure.

Let us discuss the implementation of these pointer variable as in introductory manner. Code Snippet: void swapPtr (int *_iNamX, int * _iNamY) { int _iTemp; _iTemp = *_iNamX; *_iNamX = *_iNamY; *_iNamY = _iTemp; } In following section we have a clear explanation of the above snippet.

In the above snippet, we have a function named swapPtr() having two parameter, defined as integral pointer type. The parameter named as _iNamX, and _iNamY. A part from the definiton of the function we have the calling part concerned in the main() and it is to be assumed. The claling statement of main must have two arguments, defined with addressof operator as; swapPtr(&_iPtrX, &_iPtrY); Here in the above calling statement the value stored in the memory location allocated to the variable as _iPtrX and _iPtrY is passed through the memory location where they are stored. So the parameter defined as _iNamX and _iNamY are pointing to the memory

location stored as value or are pointing to the value stored in the memo. loc. that they have. Now in the very first statement, a local integral variable _iTemp is declared. In the2nd statement the value stored in the memory location of pointer variable _iNamX that it has, is assigned to the local variable _iTemp. Then in the very next statement as 3rd, the value of the next pointer variable _iNamY gets stored in to the first pointer variable as _iNamX. At the last statement _iNamX is again assigned by the value stored in the local variable _iTemp. Congratulation you had done the job. As after these execution pattern, our desire comes to fill as we had swapped the value pointing by the memo. loc. stored in the pointer variables within there self.

10

Initially in main() _iPtrX 23 2004 &_iPtrX _iPtrY 32 2006 &_iPtrY

After Calling swapPtr(&_iPtrX, &_iPtrY) _iPtrX 32 2004 *_iNamX _iNamX _iPtrY 23 2006 *_iNamY _iNamY

11

Brief Discussion: As we came to know from the above discussion, the asterisk * operator can be concluded as the value stored in memory location where as, the address-of & operator can be concluded as the address of the value . Now let us come a bit close to the memory structure and their pointer representation. As we know a pointer variable holds the memory address of built in type variables as, an integer, a float or a character, it will be called respectively as integral pointer, float pointer, or character pointer. Each of these type pointer be further classified as near, far, and huge pointers. To understand the basic difference between these types of pointer, we need to recapitulate a few concepts of memory organization and memory addressing scheme.

12

To enable the flow of data between microprocessors and the memory there exists a set of wire called as Data Bus. Within this Data Bus each wire is responsible to transfer 1 bit of data. In practical scenario we generally use 8 bit, 16 bit, 32 bit data bus which can carry 8 bit data, 16 bit data or 32 bit data in any instance. As obvious a microprocessor with 32 bit data bus is always faster than 16 bit data bus. Here using type of data bus is completely depend upon the architecture of microprocessor. Similarly, there is another architecture of Bus called as address Bus, whose width tells how many address the microprocessor can access. Let suppose, if the address bus width of microprocessor is 20 bits then it can access 2 (to the power 20) locations calculated as 1MB in memory. The following table shows the data and address bus width as;

13

Microprocessor 8088 8086 80286 80386 80486 Pentium

Data Bus 8 bits 16 bits 16 bits 32 bits 32 bits 64 bits

Address Bus 20 bits 20 bits 24 bits 32 bits 32 bits 64 bits

Max. Memory Mode of Operation 1 MB 1 MB 16 MB 4096 MB 4096 MB 2^44 MB Real Real Real/Protected Real/Protected Real/Protected Real/Protected

From the above table (based on DOS architecture), it is the fact that in the era of 80286 and before where we are using 16 MB of memory only 1 MB comes into use. Hence two concepts as expanded memory and extended memory came in role play and the driver program to support these were called as EMM386.exe. Scope to discuss these is out of scope to the matter.

14

Running an application over DOS on any of the microprocessor of 16 bit data bus and a 20 bit address bus would be used. To access any of the 1048576 bytes (i.e. 2 to power 20) locations the microprocessor use 16-bit CPU registers. However in 16-bit registers the max. value that can be stored will be 65,535. To access memo. loc. beyond this, we use two registers as segment reg. and offset reg. in conjunction. Indeed the total memo. is divided into a number of units each comprising 64kb (65,535) locations. Each such unit is called segment and always begins with a location number which is exactly divisible by 16. This segment reg. contains the address where the segment begins, where as the offset contains the offset of data or code from where the segment begins. Following is a pictorial representation:

15

CGA MA A Block

0x8000 0xB0000 0xA0000

16

As per CGA video memory is concern, the segment address is 0xB0000 where as the offset value of the 1st CGA byte in this above segment is 0x8000. Here from the segment reg. only 1st 4 bit value can be considered. To write a character A at the specified location as 0xB000:0x8000, we need to convert this address to a form in which C can understand. This is done by simply writing the segment and offset side by side i.e. 0xB0008000 to obtain a 32 bit address. Supported syntax: char far *str; str = 0xB0008000; Where the memo. loc. 0xB0008000 has the value as character A.
17

As in the above snippet, a Far pointer is always treated as a 32 bit pointer and contains both segment and offset. A Huge pointer is also 32 bit pointer contains both segment and offset. It is computed better than far pointer due to the reason that, if we use relational operators as in comparison within far pointer type variables then the calculation may takes place through 32 bit value and result gets effected, in the other hand the huge pointer are much more normalized. A near pointer is only 16 bit long. It uses the current contents of the code segment register or current content of data segment register for the segment part, where the offset part is another 16 bit near pointer.

18

Following table shows the essence of these different types of pointers, as:
Memory Model Tiny Small Medium Compact Large Huge Code Pointer near near far near far far Data Pointer near near near far far huge 64 KB 1 MB 64 KB 1 MB 1 MB Code Size 64 KB 64 KB 64 KB 1 MB 1 MB More than 1 segment Data Size

19

Syntactical support to the concept of pointers


As Dennis Ritchie had supported the concept with the beauty with all aspects we can imagine as a programmer. We will discuss them in following sections. Sending the Address as an argument This is the same concept we had concluded in previous sections. As the function has address variable through its parameter or argument. Ex. int swapPtr(int *_iNamX, int _iNamY)

20

Function Returning Pointer Here in this approach the concept of pointer is concerned to the memory value that has been returned through the function. Ex. int * func1() { int _iNam = 20; return (&_iNam); } In the above snippet the function, named as func1() have no any argument defined but have a return of integer pointer type. In the definition part, the very 1st statement declares and initializes a integer variable as _iNam initialized by the value 20.
21

Here as per definition the address of the variable comes back to the calling function as return value. Passing Array to the Function An array can be passed to the function defined through the base location of the array. Base location of the array can be defined as the memory location of the 0th index of the array specified. Ex. int _iArr[5] = {0,1,2,3,4}; int main() { passPtrArr(&_iArr); return 0; }
22

void passPtrArr(int* _iNamPtr) { printf(0th index value of the Array = %d,*_iNamPtr); }


Here in the above snippet, the global defined array named as _iArr[] of size 5, is passed through the main() function. Basically as we are passing the array value through the address of base location it gets initialized to the pointer variable of receiving end. The memory value of the 0th index of the array is said to pass to the function as an argument and initialized in the integer type pointer variable as _iNamPtr and the concerned print function will further print the value stored in that memory address. Hence the output of the print function after execution shows as 20 which is suffix of the string defined. Behind the sense, the concept of the array says, the values gets stored in the contiguous memory location of fixed size. So as by passing the memo. loc.of 0th index of the array we can fetch the whole array value through pointers just by incrementing 1 to the pointer variable.

23

As memory allocation structure of the array is, Ex.: Single Dimension Array int _iArr[5] = = {0,1,2,3,4};
2006 0 _iArr[0] As, int* _iNamPtr = &_iArr ; 2008 1 _iArr[1] 2010 2 _iArr[2] 2012 3 _iArr[3] 2014 4 _iArr[4]

1982 2006 _iNamPtr

24

Ex.: Double Dimension Array int _iArr[3][2] = = {{0,1},{2,3},{4,5}}; As memory allocation technique;
_iArr[0][0] _iArr[0][1] _iArr[1][0] _iArr[1][1] _iArr[2][0] _iArr[2][1]

0 2006

1 2008

2 2010

3 2012

4 2014

5 2016

As the pointer variable assignment, int* _iPtrArr = &_iArr[0][0]

1982 2006 _iNamPtr

25

As above memory allocation technique, since the pointer variable has the memory address of base location we can also get the values stored in the array as, int* _iPtrArr = &_iArr[0][0]
1982 2006 _iNamPtr

_iArr[2][0] = *(_iPtrArr + 2 * size of memo. collumn + 0) = *(2006 + 2*(2+2) +0) = *(2014) 2014 i.e. value is 4 4 _iArr[2][0]

26

Conclusion Single Dimension Array _iArr[2] = *(_iPtrArr + 2 * size of memo. block) = *(2006 + 2 * 2) = *(2010) i.e. the value is 2. Double Dimension Array _iArr[2][0] = *(_iPtrArr + 2 * size of memo. collumn + 0) or _iArr[2][0] = *(*(_iArr + 2) + 0) = *(_iArr [2] + 0) = *(2014) i.e. value is 4 As Double dimension Array the concept will follow to any multi-dimensional array.

27

Returning array from Function Here we will return the array value through pointers in three sub sections; A pointer to integer int *_iNam = func1(); int* func1() { static int _iArr[][] = {{1,2},{2,3}}; return (int *) _iArr; } In the above snippet return value is a pointer which gets initialized to the another pointer type integral variable as _iNam.
28

Returning array from Function Here we will return the array value through pointers in three sub sections; A pointer to integer int (*_iNam1)[2] = func2(); int* func2()[2] { static int _iArr[][] = {{1,2},{2,3}}; return _iArr; } In the above snippet return value is a pointer which gets initialized to the another pointer of 1-D Array of type integer named as _iNam1[2].
29

Returning array from Function Here we will return the array value through pointers in three sub sections; A pointer to integer int (*_iNam2)[2][2] = func3(); int (*func3())[2][2] { static int _iArr[][] = {{1,2},{2,3}}; return (int (*)[2][2]) _iArr; } In the above snippet return value is a pointer to base address of 2-D Array, which gets initialized to the another pointer to 2-D Array variable as _iNam2[2][2].
30

Array of Pointers Since Pointer variable always contain address, so the array of pointers are just the collection of memory addresses. Ex. int *_iArr[2]; int _iNam1= 10, _iNam2= 20, _iNam3= 30; _iArr[0] = &_iNam1; _iArr[1] = &_iNam2; _iArr[2] = &_iNam3; The values can be fetch through the for loop, as follows:

31

Fetching value through array of pointers for(_i = 0; _i<=2;++_i) printf (_iArr[%d] = %d,_i,*_iArr[_i]); As per conclusion we canstore pointer variable within another pointer variable as; int ***_iPtr,**_iPtr1,*_iPtr2,_iNam; _iNam =12; _iPtr2 = &_iNam; _iPtr1 = &_iPtr2; _iPtr = &_iPtr1; printf(%d::%d::%d::%d,_iNam, *_iPtr2, **_Ptr1, ***_Ptr);

32

Pointer to Character Array Since Character are of 1 byte in size so the sequential memory allocation pattern of character is said as: Single Dimension Array char _chArr[5] = = {0,1,2,3,\0};
2006 0 2007 1 2008 2 _chArr[2] 2009 3 2010 \0

_chArr[0] _chArr[1]

_chArr[3] _chArr[4]

33

Here in above character array, we need to explicitly specify the null character within the size of the charcater array defined. This can be represented in terms of pointer variable obviously of character type as, char *_chPtr = &_chArr; Now _chPtr has the base location of the character array defined as _chArr i.e. _chArr[0].
1982 2006 _chPtr

34

2-Dimensional Character Array Same as integral or any other type the concept of 2D array is same having the sequential memo. structure as,
_chArr[0][0] _chArr[0][1] _chArr[1][0] _iArr[1][1] _iArr[2][0] _iArr[2][1]

0 2006

1 2007

2 2008

3 2009

4 2010

5 2011

Here the 2D array may be defined as, char _chArr[][] = {{0,1},{2,3},{4,5}}; Where as corresponding pointer variable will be, char* _chPtr = &_chArr;

35

Strings and Pointers We cant initialize a string variable with another string var. of dynamic size or having unknown size. But in the case of pointers, we can do so quite easily as follows, Ex. char _str[] = Hii; char *_str1[6]; _str1 = _str; Where as; char *_chPtr = Hii; char *_chPtr1; _chPtr1 = _chPtr; //Assignment allowed
36

//error as assignment not allowed.

Array of Pointers to strings: Here in the Array of pointer or array of memo. addresses we have the values as the base location of any string. Ex. char *_chPtr[] = {Abc,Def} As to retrieve the values we have statement as: printf(%s::%s,_chPtr[0],_chPtr[1]); As in pointer of type character, the compiler automatically assign last element as null, where as in the character array[], we need to explicitly assign the last character as null.

37

Structure Pointer: Structure are another heterogeneous collection of built in data type. We can represent it through concerned structure type pointer variable. Ex. struct Abc { int _iNam; float _fNam; char _chNam; }; Say struct Abc *_Ptr; struct Abc abc = {10, 3.14,A} _ptr = &abc;
38

From the above discussion we had declareda structure type pointer variable as _Ptr and assigned it through the address of the structure variable as abc. To fetch the values; printf(%d::%f::%c,_Ptr->_iNam, Ptr->_fNam, Ptr>_chNam); Here as above, when we user pointer variable to structure then in place of . dot, we need to use -> arrow operator. As in the case when a particular value of the structure is said to pass through a function. Then how can we get the whole structure values. It can be done by calculating the offset of the concerned structure.

39

Vous aimerez peut-être aussi