You are on page 1of 5

More about pointers:

Part -1 (disclaimers):

 I sometimes leave off “return 0;”. It’s slightly bad form, but C will do it for you.
 I don’t write in code for checking if the returned pointer from malloc is null; you should,
but as you said, it’s often not a problem because our computers usually have lots of
memory.

Part 0 (review)

A normal variable: A location in memory that holds a value.

A pointer: Holds the memory address of another variable. In essence, it “points” to that variable,
because that normal variable can be accessed through this pointer.

An example:

int main(){
int a; //This declares a normal int variable (like in Java)

int *p; //This declares a pointer to an int. Notice the


//asterick

a = 3;

p = &a; //The int pointer p is now assigned a value:


//it is the address of the variable a.

*p = 5; //This goes to the variable that p points to


//(in other words, a), and changes its value to 5.
//Notice that *p = 5 has the same effect as a = 5.

printf(“%d\n”, a); //This will print out 5 (value of a)

printf(“%d\n”, *p); //This will print out 5 (value of *p)

printf(“%d\n”, p); //However, this will print the


//address of p (usually a high number)

In C, arrays and pointers are very similar! In fact,


int main(){
int a[5] = {5, 6, 7, 8, 9};
//Declaring an array of 5 integers

int *p; //Declaring a pointer to an integer

//a is a pointer to the first element a[0]!

p = a; //This is valid! What it does is copies the


//address of a[0] from a to p, so now p also
//points to the same memory location;

printf(“%d\n”, p[2]); //prints out 7, which is also a[2]


//This is also a valid statement!

Part 1

You can also have pointers to pointers, as this example shows.

#include <stdio.h>

int main(){
int a; // a normal variable (int)
int *p; // a pointer to an int
int **q; // a pointer to a pointer to an int

a = 3;
p = &a; //assigns address location of a to p
q = &p; //assigns address location of p to q

printf("%d\n", a); //prints out 3


printf("%d\n", *p); //prints out 3
printf("%d\n", **q); //prints out 3

return 0;
}

What does this mean for arrays?


 In Java, we said that two-dimensional arrays were simply “arrays of arrays”
 We also said that in C, a one-dimensional integer array is really like a pointer to the
first value in that block of integers
 For two-dimensional arrays, you really have a one-dimensional array of integer
pointers, each of which points to its own subarray
 So that means the original 2D-array name is really a pointer to a pointer to an integer!
This is why pointers to pointers are important!

Earlier, we created and deleted one-dimensional dynamically-allocated arrays like this:

int main(){

//let’s say we want an array of 5 integers

int *array = (int *)malloc(5*sizeof(int));

//basically, this allocates memory/space for


//five integers. Sizeof(int) determines the size
//of one integer on the particular system (should
//be 4).

//By the way, I didn’t mention the bolded part


//earlier. malloc returns a pointer called a
//void pointer, but this basically casts that
//data type into an integer pointer (in the
//same way you could cast chars to ints in Java
//or similar). It’s just more compiler-friendly.

free(array);
//above statement frees the memory, i. e. deletes it
}

But how do we create two-dimensional arrays? Well, first we allocate memory for the initial one-
dimensional array of integer pointers, and then allocate memory for an array for each of those
new pointers. However, freeing this array becomes slightly more complicated as well (you must
free the subarrays first and then the main array, i. e. free memory in the reverse order that you
allocated it).

int main(){
int nrows = 5; //create an array of 5 "rows"
int ncolumns = 5; //and 5 "columns"

int **array; //this is a pointer to pointer to


//integer, but also a “2D-array”,
//per above
array = malloc(nrows * sizeof(int *));
//the above statement allocates memory to store the
//initial pointers to the soon-to-be-created
//subarrays. Notice the bolded part; we now need to
//allocate enough memory for each pointer. This is
//where sizeof comes in handy, because this value
//could very well change depending on computer and
//operating system.

//this loop allocates memory for each of the subarrays


for(i = 0; i < nrows; i++){
array[i] = malloc(ncolumns * sizeof(int));
}

//freeing the array – free the subarrays first


for(i = 0; i < nrows; i++)
free(array[i]);
free(array); //then free the outside array
}

Part 2

I actually found out there’s more support for complex numbers than I thought.

An example of using complex numbers:

#include <stdio.h>
#include <complex.h>

int main(){
complex double z = 2 + 3*I;
complex double a = 4 - 5*I;
complex double d = z/a;

printf("z = %f + %fI\n", creal(z), cimag(z));


printf("a = %f + %fI\n", creal(a), cimag(a));
printf("d = %f + %fI\n", creal(d), cimag(d));

return 0;
}
Important notes:
 You must include the header file <complex.h>
 Capital I is used to denote the imaginary unit.
 creal returns the real part of a complex number, cimag returns the imaginary part

You can also dynamically allocate arrays (one and two-dimensional) of complex numbers.

A one-dimensional array (allocating and freeing):

int main(){
int num_of_elements = 8; //let’s say 8 elements in array

complex double *complex_array


= malloc(num_of_elements * sizeof(complex double);

free(complex_array);

A two-dimensional array (allocating and freeing):

int main(){
int nrows = 7; //let’s say 7 rows in array
int ncolumns = 7; //and 7 columns

complex double **complex_2d_array


= malloc(num_of_elements * sizeof(complex double *);

//take note of bolded part – size of pointer

for(i = 0; i < nrows; i++){


complex_2d_array[i]
= malloc(ncolumns * sizeof(complex double));
}

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


free(complex_2d_array[i]);
free(complex_2d_array);

You might also like