C – Pointer with example

How to declare an array of functions, a function in a data structure



#include <stdio.h>

void func1(int val){
  printf("Hello, World, %d\n", val);
}
void func2(int val){
  printf("Hello, World, %d\n", val);
}

void (*funcs[2])();

typedef struct object {
  int data;
  void (*func)(int val);
}object_t;

int main() {
  object_t object;
  
  object.data = 3;
  object.func = func1;
  object.func(object.data);
  
  funcs[0] = func1;
  funcs[1] = func2;
  
  for (int i = 0; i < 2; i++) {
    funcs[i](i);
  }
  return 0;
}


How to Use the restrict Qualifier in C


In the C programming language, restrict is a keyword that can be used in pointer declarations.

By adding this type qualifier, a programmer hints to the compiler that for the lifetime of the pointer, only the pointer itself or a value directly derived from it (such as pointer + 1) will be used to access the object to which it points.

restrict limits the effects of pointer aliasing, aiding optimizations.

The C89 standards committee added two type qualifiers to C, const and volatile. The C99 committee added a third type qualifier with restrict. Individually, and in combination, these type qualifiers determine the assumptions a compiler makes when it accesses an object through an lvalue. The definition of an lvalue is an object locator, typically an identifier or the dereferencing of a pointer.

Using the restrict qualifier appropriately in C programs may allow the compiler to produce significantly faster executables.

Several important optimization techniques are based on the principle of cacheing: under certain circumstances the compiler can remember the last value accessed (read or written) from a location, and use this retained value the next time that location is read. (The memory, or cache, is typically a hardware register.) If this memory is a machine register, for instance, the code can be smaller and faster using the register rather than accessing external memory.

Objects referenced through a restrict-qualified pointer have a special association with that pointer.
All references to that object must directly or indirectly use the value of this pointer.
In the absence of this qualifier, other pointers can alias this object.
The restrict qualifier addresses the issue that potential aliasing can inhibit optimizations.

Create a 2D array


#include <stdio.h>
#include <stdlib.h>

#define ROWS 2
#define COLS 3

int main() {
  int **matrix=NULL, *ptr=NULL;
  static int val=0;
  
  matrix = malloc(sizeof(int *) * ROWS);
  for (int i = 0; i < ROWS; i++) {
    *(matrix+i) = malloc( COLS * sizeof(int) );
    ptr = *(matrix+i);
    for ( int j = 0; j< COLS; j++ ){
      *(ptr+j) = val;
      val++;
    }
  }
  
  for (int i = 0; i < ROWS; i++) {
   ptr = *(matrix+i);
    printf("%p: ", ptr);
    for ( int j = 0; j< COLS; j++ ){
      printf("%d ", *(ptr+j) );
    }
    printf("\n");
  }
  return 0;
}


0x602000000030: 0 1 2 
0x602000000050: 3 4 5 



Pass a 2D-array to a function


C does not really have multi-dimensional arrays, but there are several ways to simulate them. The way to pass such arrays to a function depends on the way used to simulate the multiple dimensions.
  • TYPE *ptr
  • ptr is an array of TYPE element
  • TYPE **ptr
  • ptr is an array of TYPE pointer

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define ROWS  3
#define COLS  4

bool printDynamicMatrix(int** m, int row_size, int col_size){
    int i=0, j=0;
    int *list=NULL;
    printf("\nprintDynamicMatrix:\n");
    for ( i=0; i<row_size; i++) {
        list = *(m+i);
        for (j=0; j<col_size; j++)
            printf("%d\n", list[j]);
    }
    printf("---\n");
    for ( i=0; i<row_size; i++) 
        for (j=0; j<col_size; j++)
            printf("%d\n", m[i][j] );
    
    return true;
}

bool printStaticMatrix(int m[][COLS], int row_size){
    int i=0, j=0;
    
    printf("\nprintStaticMatrix:\n");    
    for ( i=0; i<row_size; i++) 
        for (j=0; j<COLS; j++)
            printf("%d\n", m[i][j] );
    
    return true;
}

int main() {
    int a[ROWS][COLS] = {  
        {0, 1, 2, 3} ,   /*  initializers for row indexed by 0 */
        {4, 5, 6, 7} ,   /*  initializers for row indexed by 1 */
        {8, 9, 10, 11}   /*  initializers for row indexed by 2 */
    };
    int *b[ROWS];
    int **c=NULL;
    int i=0;
    
    /* 2 ways to create 2D array */
    /* 1.Create an array of the number of row size 
         Then, dynamically allocate memory for every row.
     */ 
    for ( i=0; i<ROWS; i++)
        b[i] = a[i];
    
    /* 2 Create an array of pointers with the number of row size 
         Then, dynamically allocate memory for every row.
     */ 
    c = malloc(sizeof(int *)*ROWS);
    for ( i=0; i<ROWS; i++ ){       
           c[i] = a[i];
    }
    
    printDynamicMatrix(b, ROWS, COLS);
    printDynamicMatrix(c, ROWS, COLS);
    printStaticMatrix(a, ROWS);

  return 0;
}

Another ex.,

#include <stdio.h>

// To execute C, please define "int main()"


void print_1d(int *arr){
  int i=0;
  printf("1D---\n");
  for ( i=0; i<10; i++)
    printf("%d ", arr[i]);
  printf("\n");
  return;
}

void print_2d(int **arr){
 int i,j;
  int *ptr=NULL;
  printf("2D---\n");
  for ( i=0; i<2; i++){
    ptr = *(arr+i);
    for ( j=0; j<10; j++){
      printf("%d ", *(ptr+j) );   
    }
    printf("\n");
  }
  
  return;
}

void change_1d(int *arr){
  int i=0;
  
  for ( i=0; i<10; i++)
    arr[i]=1;   
  
  return;
}

void change_2d(int **arr){
  int i,j;
  int *ptr=NULL;
  
  for ( i=0; i<2; i++){
    ptr = *(arr+i);
    for ( j=0; j<10; j++){
       *(ptr+j) = 2+i;   
    }
  }
  
  return;
}


int main() {
  int d1[10], d2[2][10];
  int *d2_arr[2];
  int i=0, j=0;
  
  for ( i=0; i<10; i++)
    d1[i]=0;
  
  for ( i=0; i<2; i++)
    for ( j=0; j<10; j++)
      d2[i][j]=0;  
  
  for ( i=0; i<2; i++ )
    d2_arr[i] = d2[i];
  
  print_1d(d1);
  change_1d(d1);
  print_1d(d1);
  
  print_2d(d2_arr);
  change_2d(d2_arr);
  print_2d(d2_arr); 
  
  return 0;
}


Guest ran 80 lines of C (finished in 825ms):

1D---
0 0 0 0 0 0 0 0 0 0 
1D---
1 1 1 1 1 1 1 1 1 1 
2D---
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
2D---
2 2 2 2 2 2 2 2 2 2 
3 3 3 3 3 3 3 3 3 3 




C – Pointer to Pointer (Double Pointer) with example


                                         int *pr2;
                                         int **pr1;
                                         pr1 = &pr2;


As per the diagram, pr2 is a normal pointer that holds the address of an integer variable num. There is another pointer pr1 in the diagram that holds the address of another pointer pr2, the pointer pr1 here is a pointer-to-pointer (or double pointer).

     int num=123;

     //A normal pointer pr2
     int *pr2;

     //This pointer pr2 is a double pointer
     int **pr1;

     pr1 = &pr2;

  /* Possible ways to find value of variable num*/
     printf("\n Value of num is: %d", num);
     printf("\n Value of num using pr2 is: %d", *pr2);
     printf("\n Value of num using pr1 is: %d", **pr1);

     /*Possible ways to find address of num*/
     printf("\n Address of num is: %p", &num);
     printf("\n Address of num using pr2 is: %p", pr2);
     printf("\n Address of num using pr1 is: %p", *pr1);

     /*Find value of pointer*/
     printf("\n Value of Pointer pr2 is: %p", pr2);
     printf("\n Value of Pointer pr2 using pr1 is: %p", *pr1);

     /*Ways to find address of pointer*/
     printf("\n Address of Pointer pr2 is:%p",&pr2);
     printf("\n Address of Pointer pr2 using pr1 is:%p",pr1);

     /*Double pointer value and address*/
     printf("\n Value of Pointer pr1 is:%p",pr1);
     printf("\n Address of Pointer pr1 is:%p",&pr1);

Value of num is: 123
Value of num using pr2 is: 123
Value of num using pr1 is: 123
Address of num is: XX771230
Address of num using pr2 is: XX771230
Address of num using pr1 is: XX771230
Value of Pointer pr2 is: XX771230
Value of Pointer pr2 using pr1 is: XX771230
Address of Pointer pr2 is: 66X123X1
Address of Pointer pr2 using pr1 is: 66X123X1
Value of Pointer pr1 is:  66X123X1
Address of Pointer pr1 is: XX661111

How to return an array (pointer-to-pointer) ?



#include <stdio.h>
#include <stdlib.h>

void print_arr(int arr[][4]){
  int i=0, j=0;
  
  for ( i=0; i<3; i++) {
    for (j=0; j<4; j++) {
      printf("%d ", arr[i][j]);
    }
    printf("\n");    
    }
}

int **gen_arr(){
  int **arr=NULL;
  int *row=NULL;
  int i=0, j=0;
  
  arr = (int **) malloc(sizeof(int *)*3);
  for ( i=0; i<3; i++ ){
    row = (int *) malloc(sizeof(int)*4);
    arr[i] = row;
    for ( j=0; j<4; j++){
      row[j] = 4+i+j; 
    }
  }
  
  return arr;
}

void print_arrPtr(int **arr){
  int i=0, j=0;
  int *row=NULL;
  
  for (i=0; i<3; i++){
    row = *(arr+i);
    for ( j=0; j<4; j++){
      printf("%d ", row[j]);
    }
    printf("\n");
  }
  return;
}

int main() {
  int arr[3][4]= {{1,1,1,1},{2,2,2,2},{3,3,3,3}};
  int **arr_ptr=NULL;
  int i=0;
  
  print_arr(arr);
  arr_ptr = gen_arr();
  print_arrPtr(arr_ptr);
  
  for (i=0; i<3; i++ )
    free( *(arr_ptr+i) );
  
  return 0;
}
Return an array by function's parameter:

#include <stdio.h>
#include <stdlib.h>



void return_array(int **arr){
    int *a=NULL;

    printf("arr=%p\n", arr);
    a = malloc(sizeof(int)*3);
    a[0]=7;
    a[1] = 8;
    a[2] = 9;
    *arr = a;
    printf(" a=%p, arr=%p\n", a, arr);
}

int main(){
    int *array=NULL;
    int *a=NULL;
    
    printf("&array=%p\n", &array);
    return_array(&array);
    printf("main:\n");
    printf(" array=%p\n", array);
    printf("a[0]=%d, a[1]=%d, a[2]=%d\n", array[0], array[1], array[2]);


    free(array);
}

Search a 2D Matrix


Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:
  • Integers in each row are sorted from left to right.
  • The first integer of each row is greater than the last integer of the previous row.
Example 1:
Input:
matrix = [
  [1,   3,  5,  7],
  [10, 11, 16, 20],
  [23, 30, 34, 50]
]
target = 3
Output: true
Example 2:
Input:
matrix = [
  [1,   3,  5,  7],
  [10, 11, 16, 20],
  [23, 30, 34, 50]
]
target = 13
Output: false





bool searchMatrix(int** matrix, int matrixSize, int* matrixColSize, int target){    
    int i=0;
    int row=0, col=0;
    int *r_ptr=NULL;
    

        
    col = *matrixColSize;
    row = matrixSize;
    if ( !row )
        return false;    

    if ( row == 1 ){
        r_ptr = *(matrix);
        for ( i=0; i<col; i++){
            if ( target == *(r_ptr+i) )
                return true;
        }
        return false;
    } else {
        for ( i=1; i<row; i++) {
            r_ptr = *(matrix+i);
            if ( target < *r_ptr ) {
                if (i == 1){
                    r_ptr = *matrix;
                    break;
                } else {
                    r_ptr = *(matrix+(i-1));
                    break;
                }
            }
        } // for each row

    }
    if ( i == row ) { // not in matrix or in the last row
        // search for the last row
        r_ptr = *(matrix+row-1);
        for ( i=0; i<col; i++){
            if ( target == *(r_ptr+i) )
                return true;
        }
        return false;
    }
    for ( i=0; i<col; i++){
        if ( target == *(r_ptr+i) )
            return true;
    }
    
    return false;
}


That is,
  • pointer : an array of memory cell
  • pointer-to-pointer: an array of pointers

Const Qualifier in C

  • pointer to a variable
  • 
    int *ptr = &i;
    		
  • pointer to a constant
  • 
    const int *ptr=3;
    
    *ptr = 2; // error
    		
  • constant pointer to a variable
  • 
    int i = 10;
    int j = 20;
    /* constant pointer to integer */
    int *const ptr = &i;
    
    *ptr = 100; /* valid */
    ptr = &j;	 // error
    		
  • constant pointer to constant
  • 
    	int i = 10;
    	int j = 20;
    /* constant pointer to constant integer */
    	const int *const ptr = &i;	
    
    	ptr = &j;	 /* error */
    	*ptr = 100; /* error */
    		

留言

熱門文章