Ethical Hacking Programming, Blogging, Hosting, All Computer Software, PC Software Download, JAVA in hindi, HTML, PHP, C, C++, Free Learning, Software's Download, Technical Videos, Technical Tricks and Tips, How Make Money

Pointer Arithmetic In C Programming Class 27

7.5 Pointer Arithmetic


Each variable type has a corresponding pointer type. This allows the compiler to automatically calculate the byte-o set required for indexing an array of that type. For example, on many machines a double is 8-bytes long; suppose a double-pointer pd has some initial value and is then incremented by one pd++. Now address 8-bytes organized by PD is beyond the original address, so that it points to the next double. This mechanism makes pointer arithmetic simple and uniform for all types, and hides the details of type-sizes from the programmer.

So, in general, if p is a pointer to some element of an array, then p++ increments p to point to the next element, and p += n increments it point n elements beyond where it did originally. C permits a variety of arithmetic operations to be performed on pointer types as illustrated in the following example.

float fval, array[10];

float *p1, *p2, *p3 = &array[5];
int i=2, j;
p1 = NULL; /* Assignment to NULL (or to 0 or 0L). */
p2 = &fval; /* Assignment to an address. */
p1 = p2; /* Assignment to another pointer (of same type). */
p2 = p3 - 4; /* Addition or subtraction by an integer: a pointer-offset expression. */
p2 += i; /* Another pointer-offset expression. */
j = p3 - p2; /* Pointer subtraction: gives the number of elements between p2 and p3. */
i = p2 < p3; /* Relational operations <, >, ==, !=, <=, >= */

At the end of the sequence of operations above, p1 points to the address of fval, p2 points to the fourth element of array, p3 points to the sixth element of array, i equals one, and j equals 2.

Integer arithmetic operations (i.e., pointer-o set expressions) permit access to array elements at some location relative to the current element. Relational comparisons (i.e., ==, <, >=, etc) are for determining whether the position of an array element is before or after another. And a numerical value for this relative position can be found by pointer subtraction.3

Note. The arithmetic and relational operations are only valid for pointers to elements of the same array. Their behaviour is undefined if applied to pointers from di erent arrays.

The following arithmetic operations may not be applied to pointers. Addition or subtraction by a floating-point value, and multiplication or division by a value of any type. Assignment to any


3 The result of pointer subtraction is often assumed to be of type int, and this is fine in most situations. However, the standard actually specifies a special type, ptr diff, for the result of pointer subtraction, to cater for the case where the number of elements in an array is too large to be stored in an int. The type ptr diff is defined in the standard header stddef.h.

non-pointer type is not permitted (although this can be forced using a cast). Also, while subtraction of two pointers is valid, addition of two pointers is not.
As an example of using pointer arithmetic in place of array indexing, consider the following implementations of strcpy(), a variant of the standard library function for copying a string t to a character array s. The first implementation uses array indexing.

void strcpy (char *s, char *t)

{

int i=0;

while ((s[i] = t[i]) != ’\0’)

++i;

}

Recall that an array index operation is equivalent to a dereferenced pointer o set (e.g., s[i] is equivalent to *(s+i)), so each iteration of the above loop involves three additions. The next imple-mentation increments the pointers directly.

void strcpy (char *s, char *t)

{

while ((*s = *t) != ’\0’) {

++s;

++t;

}

}

This results in just two additions per loop. The final implementation below is a common variant of the second one. It neglects the explicit comparison with \0 (as the \0 character has value zero), and moves the increment operations inside the conditional expression. The loop will now terminate when the value of *s is 0.

void strcpy (char *s, char *t)

{

while (*s++ = *t++)

;

}

This code is probably more secretive for beginners than previous implementations, but often in the C program, Learning the idioms of experienced programmers is part of the process of becoming a skilled programmer.

Style note.The efficiency advantage of pointers on array indexes is largely irrelevant with modern optimization compilers. For the above implementations of strcpy(), a good compiler would produce exactly the same executable code. It is usually bad practice to write obscure pointer-based code solely for the sake of e ciency; pointer arithmetic is best used when it makes code simpler and more readable.


A couple of lesser-known facts about pointers and arrays. First, an index can be negative so long as it still refers to an element within the array. For example,

int array[10];

int *pa = array + 5;

int i = pa[-3]; /* i equals the value of array[2] */

Second, the pointer one-past-the-end of an array is valid for pointer arithmetic.


int array[10];

int *pa, *end = &array[10];

for (pa = array; pa != end; ++pa)

*pa = end - pa; /* Values of array elements will be: 10,9,8,7,6,...,1 */

However, this pointer may not be dereferenced. A pointer one-before-the-beginning of an array may not, in general, be used for pointer arithmetic; it is non-standard but works on many (perhaps most) machines.

int array[N];
int *one_past1 = array + N; /* OK */
int *one_past2 = &array[N]; /* OK */
int val1 = *(array + N); /* Undefined */
int val2 = array[N]; /* Undefined */

int *one_before = array - 1; /* Non-standard, but works on most platforms. */

Important. Pointer accesses outside of array bounds are not checked by the compiler. For exam-ple,


int array[10];

int *pa = array + 10;

int val = *++pa; /* Invalid, but will compile OK. */

Out-of-bounds accesses are arguably the greatest source of subtle runtime bugs, rivaled only by dynamic memory issues (such as memory-leaks or accessing deallocated memory). The problem with faulty pointer arithmetic is that the error might not have an obvious e ect. In the best case, it might cause the program to crash immediately. More likely, the program will continue to run, may produce occasional weird results, and will crash unexpectedly at some critical moment (such as while demonstrating the program to a customer). It is imperative that pointers only access allocated memory regions, and that appropriate bounds checking is used to prevent access to invalid memory locations.


7.6 Return Values and Pointers


A function may return a pointer. For example,

int* func_returns_pointer(void);

However, there is a mistake in returning an indicator in many situations and which will not be expected. The problem arises, if the object in which the context of the pointer is local to the reference function. When the function ends, the local object will be deleted, and the address returned will point to an invalid location. This error also applies to the arrays defined within the task, in the following example,

int* misguided(void)

{

int array[10], i; /* array has local extent: destroyed at end-of-block. */

for (i = 0; i < 10; ++i)

array[i] = i;

return array;

}



the pointer to array ceases to refer to valid memory once array has been destroyed.

Returning pointers from functions is fine provided the object pointed-to remains in existence.

Thus, it is valid to return a pointer to a static variable (which has static extent).

double* geometric_growth(void)

{

static double grows = 0.1; /* grows exists for lifetime of program. */

grows *= 1.1;

return &grows;

}

Similarly, variables with dynamic extent (i.e., variables allocated using malloc()) can be safely returned by a pointer. Pointers may also be returned if they refer to a function input argument which is itself a pointer. For example, a pointer might refer to an element within a passed array.

char* find_first(char* str, char c)

/* Return pointer to first occurrence of c in str. Return NULL if not found. */

{

while(*str++ != ’\0’)

if (*str == c) return str;

return NULL;

}

Share:

No comments:

Post a Comment

Follow On YouTube