I'm studying pointers in C language with Ted Jensen's "A TUTORIAL ON POINTERS AND ARRAYS IN C" manual. It's a very prickly argument.
Question 1. I have come to program 3.1 and would like a clarification. This is the program:
#include <stdio.h>
char strA[80] = "A string to be used for demonstration purposes";
char strB[80];
int main(void) {
char *pA;
char *pB;
puts(strA);
pA = strA;
puts(pA);
pB = strB;
putchar('\n');
while(*pA != '\0')
{
*pB++ = *pA++;
}
*pB = '\0';
puts(strB);
return 0;
}
Regarding the line pA = strA;, the book says "We then [point] the pointer pA at strA. That is, by means of the assignment statement we copy the address of strA [0] into our variable pA", which is what I don't understand.
To copy the address of strA[0] into our variable pA via the assignment declaration, shouldn't we write pA = & strA?
Question 2. The expression c = * ++ p; increases the value of p or the address of p?
Does the indirection operator (*) not indicate the value of the pointed variable?
To copy the address of strA [0] into our variable pA via the assignment declaration, shouldn't we write pA = & strA?
&strA is the address of strA. &strA[0] is the address of strA[0]. These are the “same” in the sense they point to the same place in memory, but they have different types, and the compiler would complain if we wrote pA = &strA when the type of pA is a pointer to the type of the elements of strA.
When we write pA = strA, the array strA is automatically converted to a pointer to its first element, so pA = strA is equivalent to pA = &strA[0].
Question 2: the expression c = * ++ p; increases the value of p or the address of p?
The C grammar organizes this as c = *(++p);, and ++p increases the value of p. If p is a pointer, it increases the value of that pointer. The * operator uses the increased value.
Be careful about speaking of the address of a pointer. The value of the pointer is an address, but you should not say that is the address of the pointer. The pointer is itself an object in memory, and so it has an address in memory where its value is stored. The address where a pointer is stored is different from the address stored in it. The “address of a pointer” is the address where the pointer is stored, not the value of the pointer.
It's simply because strA, which is char array, is a pointer.
An array's "value" is actually nothing more than the address of the first element of array.
When you assign address of primitive data type(int, char, etc..), you should assign it in the way you described.
int x;
int *pA;
pA = &x;
When you assign address of pointer data type(array, etc..), you should assign it without & operator, since the value is in itself the address.
int x[10];
int* pA;
pA = x;
Original code
#include <stdio.h>
char strA[80] = "A string to be used for demonstration purposes";
char strB[80];
int main(void)
{
char *pA; /* a pointer to type character */
char *pB; /* another pointer to type character */
puts(strA); /* show string A */
pA = strA; /* point pA at string A */
puts(pA); /* show what pA is pointing to */
pB = strB; /* point pB at string B */
putchar('\n'); /* move down one line on the screen */
while(*pA != '\0') /* line A (see text) */
{
*pB++ = *pA++; /* line B (see text) */
}
*pB = '\0'; /* line C (see text) */
puts(strB); /* show strB on screen */
return 0;
}
In C, when you write :
char strA[80];
Memory is allocated for your table. This is an example for you to try and visualize what it looks like.
[0] 1st Element
[1] 2nd Element
[2] 3rd Element
[....] ....
[n] nth Element
0000
0001
0002
0003
n
strA is a pointer to the address where your table starts in the memory (0000 in our example), which is the same as the address of its first element strA[0].
So when you write
pA = strA
you are actually copying the first element's address (0000 in our example) to pA
To copy the address of strA [0] into our variable pA via the assignment declaration, shouldn't we write pA = & strA?
Arrays are weird and don't behave like other types.
The expression strA "decays" from type "N-element array of char" to "pointer to char", and the value of the expression is the address of the first element. This "decay" doesn't happen when the array expression is the operand of the sizeof or unary & operators, so the expression &strA has type "pointer to N-element array of char", or char (*)[N], which is not the same as char *. The address value is the same (the address of an array is the same as the address of its first element), but the types are different.
Assuming the declarations
char str[N]; // for some size N
char *p;
when you write
p = str; // char * = char *
the expression str has type "N-element array of char"; however, since str is not the operand of the sizeof or unary & operators, it "decays" to type char * and evaluates to the address of the first element. It’s equivalent to writing
p = &str[0]; // char * = char *
There is a reason for this - C was derived from an earlier language named B, and in B array types had a dedicated pointer to the first element - when you declared an array in B like
auto a[N];
what you got in memory was
+---+
a: | | -------+
+---+ |
... |
+---+ |
| | a[0] <-+
+---+
| | a[1]
+---+
...
and the array subscript operation a[i] was defined as *(a + i) - given the starting address a, offset i elements from that address and dereference the result.
When he was designing C, Ritchie wanted to keep B's array behavior, but he didn't want to keep the explicit pointer that behavior required. When you declare an array in C like
int a[N];
what you get in memory is
+---+
a: | | a[0]
+---+
| | a[1]
+---+
...
Instead of setting aside space for an explicit pointer to the first element, the compiler replaces any occurrences of the expression a with a pointer to a[0]. So a[i] is still defined as *(a + i). Unfortunately, this means that arrays lose their "array-ness" under most circumstances and most of the time what you're dealing with is a pointer.
Question 2: the expression c = * ++ p; increases the value of p or the address of p?
This gets a little complicated. To answer as asked, it increases the value of p - it sets p to point to the next object in a sequence. This is probably better explained with a concrete example.
Assume the following declarations:
char str[] = "foo";
char *p = str;
then the following are true:
+---+
str: |'f'| str[0] <--- p
+---+
|'o'| str[1] <--- p + 1
+---+
|'o'| str[2] <--- p + 2
+---+
| 0 | str[3] <--- p + 3
+---+
p == &str[0] // char * == char *
*p == str[0] == 'f' // char == char == char
p + 1 == &str[1]
*(p + 1) == str[1] == 'o'
p + 2 == &str[2]
*(p + 2) == str[2] == 'o'
The result of the expression p + 1 is a pointer to str[1], the result of the expression p + 2 is a pointer to str[2], etc.
c = *++p; is roughly equivalent to writing
tmp = p + 1;
c = *tmp;
p = p + 1;
with the caveat that the updates to c and p can happen in any order - they may even be evaluated simultaneously (either interleaved or in parallel).
In this case, it means we assign the value of *(p + 1) ('o') to c, and update p to point to str[1], leaving us with this:
+---+
str: |'f'| str[0]
+---+
|'o'| str[1] <--- p
+---+
|'o'| str[2] <--- p + 1
+---+
| 0 | str[3] <--- p + 2
+---+
p == &str[1]
*p == str[1] == 'o'
p + 1 == &str[2]
*(p + 1) == str[2] == 'o'
p + 2 == &str[3]
*(p + 2) == str[3] == 0
Related
So I know that the * operator is used for multiplication and as a pointer but sometimes I see the * operator and I am not sure what it means. Have a look at this code which defines a matrix
#ifndef MATRIX_H
#define MATRIX_H
/* The data structure representing a matrix */
typedef struct {
int rows; /* number of rows */
int columns; /* nuumber of columns */
int **content; /* matrix elements in a two dimensional array */
} matrix_t;
what does a double asterisk used for here?
I assume ** operator is used for pointers in 2d arrays but I am not sure.
Multiple indirection is a thing - you can have pointers to pointers, pointers to pointers to pointers, pointers to arrays of pointers, arrays of pointers to pointers, pointers to arrays of pointers to pointers to arrays of pointers to functions returning pointers, etc.
As used here, the intent is that you allocate an array of pointers:
matrix_t mat;
mat.content = calloc( 2, sizeof *mat.content );
which gives us
int ** int *
+---+ +---+
mat.content: | | ---> | | mat.content[0]
+---+ +---+
| | mat.content[1]
+---+
and then for each of those pointers, you allocate an array of int:
for ( size_t i = 0; i < rows; i++ )
mat.content[i] = calloc( 2, sizeof *mat.content[i] );
giving us
int ** int * int
+---+ +---+ +---+
mat.content: | | ---> | | mat.content[0] ---> | | mat.content[0][0]
+---+ +---+ +---+
| | mat.content[1] -+ | | mat.content[0][1]
+---+ | +---+
|
|
| +---+
+-> | | mat.content[1][0]
+---+
| | mat.content[1][1]
+---+
The expression mat.content has type int **, so the expression *mat.content has type int *; thus, sizeof *mat.content == sizeof (int *). Similarly, the expression mat.content[i] also has type int * (*p == p[0]), so *mat.content[i] has type int, so sizeof *mat.content[i] == sizeof (int).
Because of how array subscripting works, mat.content[i][j] works exactly the same way as if you had declared mat.content as a regular 2D array of int. It's just instead of all the rows being allocated in a single contiguous chunk, they're allocated piecemeal.
General rules:
T *p; // p is a pointer to T
T *ap[N]; // ap is an array of pointer to T
T (*pa)[N]; // pa is a pointer to an array of T
T *fp(); // fp is a function that returns pointer to T
T (*pf)(); // pf is a pointer to a function that returns T
T **p; // p is a pointer to a pointer to T
T ***p; // p is a pointer to a pointer to a pointer to T
const T *p; // p is a pointer to const T - you can write to p, but not *p
T const *p; // same as above
T * const p; // p is a const pointer to T - you can write to *p, but not to p
When used in an expression, the * "dereferences" the pointer - if you have a declaration like
int x;
int *p = &x;
the expression *p acts as kind of an alias for x:
*p = 10; // does the same thing as x = 10;
The object p stores the location of x, and the type of the expression p is int * (pointer to int). The expression *p is equivalent to the expression x - not only does it yield the value stored in x, you can write a new value to x through *p as shown above.
The declarations above give us this relationship:
p == &x // int * == int *
*p == x // int == int
The array subscript expression a[i] is defined as *(a + i) - given a starting address designated by a, offset i elements (not bytes!) from that address and dereference the result.
*p == *(p + 0) == p[0]
Arrays are not pointers, nor do they store a pointer to their first element. Unless it is the operand of the sizeof, _Alignof, or unary & operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T" will be converted, or "decay", to an expression of type "pointer to T" and the value of the expression will be the address of the first element. This is important - if you declare an array
int a[10];
a does not store an address to its first element; instead, any time the compiler sees the expression a outside of the contexts listed above, it will basically replace it with something equivalent to &a[0].
Code
short **p = (short **)malloc(sizeof(short *));
*p = malloc(sizeof(short));
**p = 10;
printf("**p = %d", **p);
Output
**p = 10
In this code, a multiple pointer **p is declared and *p is used without any declaration(maybe it's by **p).
What does *p mean in my case? Sorry for very simple question.
I saw C standard and stack overflow, but I couldn't find out something.
For any array or pointer p and index i, the expression p[i] is exactly equal to *(p + i) (where * is the unary dereference operator, the result of it on a pointer is the value that the pointer is pointing to).
So if we have p[0] that's then exactly equal to *(p + 0), which is equal to *(p) which is equal to *p. Going backwards from that, *p is equal to p[0].
So
*p = malloc(sizeof(short));
is equal to
p[0] = malloc(sizeof(short));
And
**p = 10;
is equal to
p[0][0] = 10;
(**p is equal to *(*(p + 0) + 0) which is equal to *(p[0] + 0) which is then equal to p[0][0])
It's important to note that the asterisk * can mean different things in different contexts.
It can be used when declaring a variable, and then it means "declare as pointer":
int *p; // Declare p as a pointer to an int value
It can be used to dereference a pointer, to get the value the pointer is pointing to:
*p = 0; // Equal to p[0] = 0
And it can be used as the multiplication operator:
r = a * b; // Multiply the values in a and b, store the resulting value in r
short **p = (short **)malloc(sizeof(short *));
This line declares a pointer to a pointer p. Additionally the value of p is set to the return value from malloc. It is equivalent to
short **p;
p = (short **)malloc(sizeof(short *));
The second line
*p = malloc(sizeof(short));
Here *p is the value of p. *p is of type pointer. *p is set to the return value of malloc. It is equivalent to
p[0] = malloc(sizeof(short));
The third line
**p = 10;
**p is the value of the value of p. It is of type short. It is equivalent to
p[0][0] = 10
In effect what the code above does is to allocate a 2D array of short, then allocate memory for the first row, and then set the element p[0][0] to 10.
As a general comment on your code, you should not use typecast in malloc. See Do I cast the result of malloc?
What does *p mean when **p is already declared?
short **p = (short **)malloc(sizeof(short *));
(better written as)
short **p = malloc (sizeof *p);
Declares the pointer-to-pointer-to short p and allocates storage for a signle pointer with malloc and assigns the beginning address for that block of memory to p. See: In C, there is no need to cast the return of malloc, it is unnecessary. See: Do I cast the result of malloc?
*p = malloc(sizeof(short));
(equivalent to)
p[0] = malloc (sizeof *p[0]);
Allocates storage for a single short and assigns the starting address for that block of memory to p[0].
**p = 10;
(equivalent to)
*p[0] = 10;
(or)
p[0][0] = 10;
Assigns the value 10 to the dereference pointer *p[0] (or **p or p[0][0]) updating the value at that memory address to 10.
printf("**p = %d", **p);
Prints the value stored in the block of memory pointed to by p[0] (the value accessed by dereferencing the pointer as *p[0] or **p)
The way to keep this straight in your head, is p is a single pointer of type pointer-to-pointer-to short. There are 2-level of indirection (e.g. pointer-to-pointer). To remove one level of indirection, you use the unary * operator, e.g.
*p /* has type pointer-to short */
or the [..] also acts as a dereference such that:
p[0] /* also has type pointer-to short */
You still have a pointer-to so you must remove one more level of indirection to refernce the value stored at the memory location pointed to by the pointer. (e.g. the pointer holds the address where the short is stored as its value). So you need:
**p /* has type short */
and
*p[0] /* also has type short */
as would
p[0][0] /* also has type short */
The other piece to keep straight is the type controls pointer-arithmetic. So p++ adds 8-bytes to the pointer-to-ponter address so it now points to the next pointer. If you do short *q = (*p)++; (or short *q = p[0]++, adds 2-bytes to the address for the pointer-to-short, soqnow points to the nextshortin the block of memory beginning at*p(orp[0]`). (there is no 2nd short because you only allocated 1 -- but you get the point)
Let me know if you have further questions.
Let me put it in different way,
consider an example,
int x;
int *y = &x;
int **z = &y;
x = 10;
Which simplifies to this,
Note: Only for illustration purpose I have chosen address of x,y,z as 0x1000,0x2000,0x3000 respectively.
What does *p mean in my case?
In short the snippetshort **p = (short **)malloc(sizeof(short *)); is dynamically allocating a pointer to a pointer of type short i.e same asy in my example.
For example let's say you have an array a and a pointer p.Here it is how it goes.
void main() {
int a[10];
int *p;
for(i = 0;i <=10;i++)
a[i] = (i + 1) * 2;
p = &a[0];
printf("%d",a[4]);
printf("%d",p[4]);
}
How are they equal ?
How come the first element of an array is equal to the array ?. Lets say you have an integer array like int arr[5]; then according to your question headline
first element of an array will be arr[0] which is value of arr[0] and
array means arr and arr names represents base address of the array. So arr and arr[0] are not same. arr is base address & arr[0] is value.
For your particular case, integer array a looks like below & all elements of array are stored in consecutive memory location. Assume array base address is 0x100(some memory location)
a[0] a[1] a[2] a[3] ........................................ a[9]
------------------------------------------------------------------------
| 2 | 4 | 6 | 8 | 10 | 12 | 14 | 16 | 18 | 20 | 22 |
------------------------------------------------------------------------
0x100 0x104 0x108 .. ..
a
LSB MSB
So here a means 0x100, by assuming base address of a is 0x100. Now when you do
p = &a[0]; /* here you are setting p to point to one of the places in the array a and that is a[0] */
here p is pointing to first element of a i.e 0x100 as below
a[0] a[1] a[2] a[3] ........................................ a[9]
------------------------------------------------------------------------
| 2 | 4 | 6 | 8 | 10 | 12 | 14 | 16 | 18 | 20 | 22 |
------------------------------------------------------------------------
0x100 0x104 0x108 0x112 0x116.. ..
a
|
p
Now when you print a[4] it prints 10 which is quite simple as expected & it expands like below
a[4] = *(a + 4) /* here you can say that array name a is converted to a pointer to its first element */
= *(0x100 + 4*4 ) /* multiplied by 4 ? bcz a is int array & each element size is 4 byte */
= *(0x116) /* value at 0x116 memory location */
= 10
And when you print p[4] it expands like below
p[4] = *(p + 4)
= *(0x100 + 4*4) /*multiplied by 4 because int pointer increments by 4 bytes*/
= *(0x116) ? /* it prints value at 0x116 location which 10 */
= 10
Also while assigning values to array elements in the for loop, you are trying to access a[10] which is out of boundary & causes undefined behavior. In the below code block condition part should be i<10 instead of i<=10 as you declared a[10] and array index starts from zero.
for(i = 0;i <=10;i++) { /* make it i<10 */
a[i] = (i + 1) * 2;
}
Finally void main() { /* code */ } is bad practice and its not according to C standards specification. Use int main(void) { } instead as specified in C standard n1256 draft.
5.1.2.2.1 Program startup
1 The function called at program startup is named main. The
implementation declares no prototype for this function. It shall be
defined with a return type of int and with no parameters:
int main(void) { /* ... */ }
or with two parameters (referred to here as argc and argv, though any
names may be used, as they are local to the function in which they are
declared):
int main(int argc, char *argv[]) { /* ... */ }
or equivalent;9) or in some other implementation-defined manner.
Array definition: An array is a series of elements of the same type placed in contiguous memory locations that can be individually referenced by adding an index to a unique identifier.
When you take the address of the first element of the array (&a[0]), you will get the exact same value as a. (however you will lose the size information, as &a[0] is a pointer to the memory, where a is actually the array)
This is because a[0] actually translates to *(a + 0), where a is the pointer to the memory address your array resides at. So &a[0] becomes &(*(a + 0)) or "the address of the content of the address a + 0", which is the same as "the address a"
Similarly, a[4] translates to *(a + 4).
I hope this clarifies things :)
EDIT:
I just found this page, where you can read more about it:
https://www.le.ac.uk/users/rjm1/cotter/page_59.htm
EDIT 2:
Clarified the difference between &a[0] and a
Arrays are stored in contagious memory and &a[0] is a pointer reference to first element. Now if you want to get pointer reference to second that would be (address of first element + sizeof(int)). Now you can access it's value by *(address of first element + sizeof(int). This is called pointer arithmetic. You must refer to a good book to learn more about it.
You assigned pointer ‘p’ to point the local array ‘a’,
so from now on ‘p’ and ‘a’ are the same array,
every change you make to ‘p’ will influance directly on ‘a’ and vice versa.
p = &a[0];
In a[10], a is a pointer which points to the address of first element of the array. So When you assigned:
p = &a[0];
P is also storing the same address at that of a and point to same element. So any manipulation made to p will be reflected in a.
When you write
p=&a[0];
is the same as
p=a;
now p and a are pointers on the beginning of the same array
int num = 78;
int *p;
int array[SIZE] = {0,1,2,3,4};
char c[SIZE] = {'A', 'B', 'C', 'D', 'E'};
p = array[3];
*p = (int) *c;
p++;
array[4] = num;
p++;
p = c;
p++;
I'm trying to figure out the memory behind this above code. I understand that the pointer p initially points to the 3rd element of the array(which is 3). I have no idea what the next line *p = (int) *c; means. Can anyone please explain that line of code??
Edit:
After the p is incremented as such can anyone explain what it would be pointing to?
You should use 'p = &array[3];'. The pointer will then point to the third element of the array i.e. 'C'
*p = (int) *c;
c[size] is an array. c is the base pointer of the array. so *c is the value at the base pointer which is 'A'. This statement will put 'A' in the third element of the array. So the array now contains A, B, A, D, E
p = array[3]; // int * = int
is an error; the types don't match, and the compiler will yell at you for it. The type of p is int *, and the type of array[3] is int.
There are two ways to fix this, depending on what you want to do. If you want to set p to point to array[3] (which is what you want to do in this case), you would write
p = &array[3]; // int * = int *
If you want to write the value of array[3] to the object that p points to (which is not what you want to do in this case, since p isn't pointing anywhere valid yet), you would write
*p = array[3]; // int = int
In this case, we want to set p to point to array[3], so we use the first statement. After doing that, the following are true:
p == &array[3] // int *
*p == array[3] == 2 // int
Now we have the statement
*p = (int) *c;
is saying "take the value of the char object that c points to, convert it to an int value1, and assign the result to the object that p points to."
Except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize an array of char in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.
The expression c has type "5-element array of char". Since it is not the operand of the sizeof or unary & operators, it is converted to an expression of type char *, and the value of the expression is the address of the first element in the array, c[0]. Thus:
c == &c[0] // char *
*c == c[0] == 'A' == 65 (ASCII) // char
Taking all that together, that means
*p = (int) *c;
is another way of writing
*p = (int) c[0];
which is another way of writing
array[3] = (int) c[0];
which is another way of writing
array[3] = (int) 'A';
which is another way of writing
array[3] = 65;
(int) is a cast expression; it means that the value following it should be treated as type int.
*p = (int) *c;
*c means that you take the value at the address of c
(int) casts it to an int
*p= writes to the address p points to
So if you fix what droppy said, there will be the numerical value of c[0] in the 3rd part of array
so it would be 1,2,65,4,5
#define N 20
int a[2N], i, *p, sum;
p = a;
/* p=a is equivalent to p = *a[0];
• p is assigned 300.
• Pointer arithmetic provides an alternative to array indexing.
• p=a; is equivalent to p=&a[=]; (p is assigned 300)
Here I am not getting how p=*a[0] and p=&a[0] are same? *a[0] references the element at the memory address.
Point 1
Do your understand, here int a[2N] is invalid code?
This 2N does not mean 2*N, rather this N is considered as a suffix (to integer literal 2) which is invalid.
Thanks to Mr # Lưu Vĩnh Phúc for the comment below.
If you wanted something like int a[40], write int a [2*N]
Point 2
p=*a[0] and p=&a[0] are same
No, they're not same. Actually, with the current code snippet, *a[0] is invalid.
FWIW, p = a; and p = &a[0]; are same, because the array name represents the base address, i.e., the address of the first element in the array.
p = a and p = &a[0] are indeed equivalent. In this case, you assign the address of the first element in the array to p (because the name of the array = pointer to its first element). p=*a[0] and p=&a[0] are not the same; *a[0] requires that a be an array of pointers, and dereferences its first member.
The meaning of p = &a[0] is as follows
For example :
int a[4];
a[0] a[1] a[2] a[3]
a --------> [ ][ ][ ][ ]
Equivalents
// Reference
&a[0] = a;
&a[1] = a+1;
...
&a[3] = a+3;
// Value
a[0] = *a
a[1] = *(a+1)
..
a[3] = *(a+3)
In arrays of C programming, name of the array always points to the first element of an array. Here, address of first element of an array is &a[0]. Also, a represents the address of the pointer where it is pointing i.e., base address . Hence, &a[0] is equivalent to a, so p = a or p = &a[0] both are same.