I am trying to increment an int array using a variable as the increment but it throws an error.
int array[MAXSIZE];
int n;
//fill the array with some numbers
//some other code
The situation here is that once I analyze the first "n" numbers i will not need them again and it will be a waste of cycles to iterate the array from the starting so i want to increment the array by "n".
NOTE: because of the type of the problem that I'm working on I cannot just
save the position in a variable and start from that position later using array[position]; I have to increment the pointer permanently.
array += n;
and Throws this error: incompatible type in assignment.
I don't know in advance what "n" is going to be. I tried to use
array += sizeof(int)*n; but it fails as well.
int array[MAXSIZE];
array is an array and not a pointer. You can not increment an array variable.
You can do something like:
int *p = array;
p += whatever;
just make sure that you don't deference p when it is pointing to any element beyond the last element of the array.
The fact that printing out array and p will give you the same output (address) does not make them the same things.
According to the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
3 Except when it is the operand of the sizeof operator or the unary &
operator, or is a string literal used to initialize an array, an
expression that has type ‘‘array of type’’ is converted to an
expression with type ‘‘pointer to type’’ that points to the initial
element of the array object and is not an lvalue. If the array
object has register storage class, the behavior is undefined.
So you may not change an array such a way as
array += n;
So just use one more variable of the type int *. For example
int array[MAXSIZE];
int n;
//...
int *p = array;
p += n;
an array name is a type * const array_name so you can't move it.(pay attention it is a const pointer)
you can define a pointer yourself and then move it. for example:
int *arr = new int[siz];
or in c:
int *arr = (int *)malloc(n * sizeof(int));
if your source code is in a .c file, you do not need to do casting.
If you are trying to fill the array with data, then you will need to index into the array.
int array[MAXSIZE];
int i;
for (i = 0; i < MAXSIZE; i++) {
array[i] = rand();
}
If you genuinely want to make use of a pointer, and do 'pointer arithmetic' then you must be careful.
int array[MAXSIZE];
int *p;
int i;
p = &(array[0]);
for (i = 0; i < MAXSIZE; i++) {
*p = rand();
p += 1;
}
Pointer arithmetic may not work as you expect... Doing p += 1 does not move the pointer along one byte, or even one int, but it will move the address along the size of the variable's de-referenced type.
Do an experiment:
#include <stdio.h>
void main(void) {
struct info {
int a;
int b;
};
struct info array[10];
struct info *p;
int n;
p = &(array[0]);
printf("sizeof(*p): %zu\n", sizeof(*p));
for (n = 0; n < 10; n++) {
printf("address: %p\n", p);
p += 1;
}
}
This will advance p's value by sizeof(*p) each time around the loop.
#include<stdio.h>
#include<stdlib.h>
#define MAX 100
int main()
{
int array*,i,n;
printf("Enter size of array:\n");
scanf("%d",&n);
array = malloc(n*sizeof(int));
/* code to enter numbers in array */
array += n;
//remember to free pointers after you are done with them
free(array);
return 0;
}
This should do it.
Related
I am trying to print a 2-D array in C by using pointers but I am not getting the expected output.
Program:-
#include <stdio.h>
int main()
{
int arr[2][3] = {{1,2,3},{4,5,6}};
int* p;
for ( p = arr; p <= arr+6; p++)
{
printf("%d ", *p);
}
return 0;
}
Output:-
1 2 3 4 5 6 -1116112128 1587637938 0 0 1893963109 32521 -1453950296 32766 -1453805568 1 800797033 21984 -1453949463
Could you tell me where I am wrong as the output should only be:
1 2 3 4 5 6
Could you tell me where I am wrong
The elements of arr are not integers, but arrays of 3 integers. So arr+6 is surely a different address than what you expect, since pointer arithmetic works in multiples of the size of the type in the array.
You'll always be better off using nested loops to iterate over a multidimensional array; treating it as one single-dimensional array of int leads to exactly the kinds of confusion you see here. The code is harder to understand and verify, it won't be any slower.
First, when looping through arrays of size n wth an index i, the condition for continuation should be i < n rather than i <= n, because array indexes in C run from 0 through n-1.
However, your code has a more serious error: 1-dimensional arrays can be 'decayed' into pointers to the elements' type; however, 2-dimensional arrays decay into pointers to 1-dimensional arrays. So, in your case, the type of the pointer used in the arr + 6 expression is a pointer to an array of three integers; further, when the 6 is added, that operation is performed in terms of the size of the pointed-to object, which is sizeof(int) * 3 – so, even when changing the <= to <, you will be running far beyond the actual bounds of the array.
To make the pointer arithmetic work in the correct 'units' (i.e. sizeof(int)), cast the arr to an int* before the addition (and also change the <= to <):
#include <stdio.h>
int main()
{
int arr[2][3] = { {1,2,3},{4,5,6} };
int* p;
for (p = (int*)arr; p < (int*)arr + 6; p++) {
printf("%d ", *p);
}
return 0;
}
You are trying to access the value in the wrong way, The two-dimensional array is saved as a continuous block in the memory. So, if we increment the value of ptr by 1 we will move to the next block in the allocated memory.
int arr[2][3] = {{1,2,3},{4,5,6}};
int *ptr = arr;
int i,j;
for (i = 0; i < 6; i++) {
printf("%d ", *(ptr + i));
}
return 0;
Array designators used in expressions with rare exceptions are implicitly converted to pointers to their first elements.
The type of the array elements of this array
int arr[2][3];
is int [3]. So a pointer to the first element of the array has the type int ( * )[3].
This assignment
p = arr;
where p has the type int * is incorrect because the operands of the assignment have incompatible pointer types.
At least you need to cast the right expression to the type int * like
p = ( int * )arr;
The same casting you need to use in the condition in the for loop. That is instead of
p <= arr+6
you have to write
p < ( int * )arr+6
Below there is a demonstration program that shows how to output a two-dimensional array as a two-dimensional array using pointers.
#include <stdio.h>
int main( void )
{
int arr[2][3] = {{1,2,3},{4,5,6}};
for ( int ( *p )[3] = arr; p != arr + 2; p++ )
{
for ( int *q = *p; q != *p + 3; ++q )
{
printf( "%d ", *q );
}
putchar( '\n' );
}
return 0;
}
If you want to output the two-dimensional array as a one-dimensional array then you can write
#include <stdio.h>
int main( void )
{
int arr[2][3] = {{1,2,3},{4,5,6}};
for ( int *p = ( int * )arr; p != ( int * )arr + 6; p++ )
{
printf( "%d ", *p );
}
putchar( '\n' );
return 0;
}
In
for ( p = arr; p <= arr+6; p++)
the expression arr, as an rvalue, is a pointer to the first element of the array (which is of type int [3], so each time you increment that pointer, it moves three int positions forward ---a whole row---, and so, arr + 6 points just after the sixth row of the array (if the array should ever had six rows) You can do it (with the proper explicit pointer conversions, as you are mixing pointers to int with pointers to int [3]) with the expression arr + 2 which is the addres of the first array element after the second row (and the number of rows of the array).
You can do it also declaring
int (*aux)[2][3] = &arr; /* aux is a pointer to the whole 3x2 array,
* so aux + 1 will be the position of the second
* 2D array after this one */
and then
int *end = (int *)(aux + 1);
or simply
int *end = (int *)(&arr + 1); /* see below */
(Beware that arr and &arr are both pointers and point to the same place, but they are not the same type (arr is of type int (*)[3] and &arr is of type int(*)[2][3])
So let's rewrite your code as
for (p = (int *)arr; p < end; p++)
or
for (p = (int *)arr; p < (int *)&arr + 1; p++)
would work, which seems more natural to do the calculus in complete array units than in rows or single cells (and you can change freely the dimensions of the array)
Your code would be:
#include <stdio.h>
int main()
{
int arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
int *end = (int *)(&arr + 1); /* try to avoid evaluating this expression in the loop
* despite that it can be optimized to comparing
* with a constant value */
char *sep = "";
for (int *p = (int *)arr; p < end; p++)
{
printf("%s%d", sep, *p);
sep = ", ";
}
putchar('\n');
return 0;
}
(Beware that you have to use < operator and not <= as you don't want to print the value pointed by end, because it lies one place outside of the array)
Finally a note: this will work with true arrays, but not with function parameters declared as arrays, because they decay to pointers and then &arr is not a pointer to data the size of the array, but it is the address of the parameter itself, which points to the array somewhere else.
I would like to insert value into the array's last position. So, I created the function insert. This function returns the new array.
In this code, I would like to insert value=0 into array={1}'s last position and assign the new array to an array I declare at the beginning of the main.
So I wrote:
array = insert(&array[0], value, NUM(array), NUM(array)+1)
However, I received the error:
ERROR: assignment to expression with array type` in the line:
`array = insert(&array[0], value, NUM(array), NUM(array)+1);
but if I declare a new_array this error does not occur.
I would like to know why this occurs and how to solve it.
Thanks.
#include <stdio.h>
#define NUM(a) (sizeof(a) / sizeof(*a))
int * insert(int *, int, int, int);
void main(){
int array[] = {1};
// int *new_array;
int value = 0;
int num = 3;
int pos = 2;
array = insert(&array[0], value, NUM(array), NUM(array)+1);
int i;
for(i = 0; i < NUM(array); i++) {
printf("array[%d] = %d\n", i, array[i]);
}
}
int * insert(int *p, int a, int N, int pos){
int i;
// // now shift rest of the elements downwards
// for(i = N; i >= 0; i--) {
// p[i+1] = p[i];
// }
// increase the size by 1
N++;
// shift elements forward
for (i = N-1; i >= pos; i--)
p[i] = p[i - 1];
// insert x at pos
p[pos - 1] = a;
return p;
}
In C, array names are non modifiable lvalues. You cannot assign anything to an array variable. Hence, you are getting error on this statement:
array = insert(&array[0], value, NUM(array), NUM(array)+1);
new_array is a pointer and remember arrays and pointers are different. When you access an array, it is converted to a pointer to first element (there are few exceptions to this rule)1).
Also note that
int array[] = {1};
the size of array array is 1. When you omit the dimension of an array, compiler deduce it based on the size of initialiser and you are initialising array with only one element. So, the array array is an array of one int type element.
That means, this
int array[] = {1};
is same as this
int array[1] = {1};
You are passing NUM(array)+1 to insert() function and accessing array element at pos index, where pos value is NUM(array)+1, i.e. accessing array beyond its size, which is an undefined behaviour.
Also, you should not use void as return type of main() function . As per C language standards, the return type of main() function should be int.
From C11 Standards#6.3.2.1p3 [emphasis added]
3 Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ''array of type'' is converted to an expression with type ''pointer to type'' that points to the initial element of the array object and is not an lvalue. ....
Learning C and this confusing me:
#include <stdio.h>
int main(){
int m[5][5];
int count = 0;
for(int i = 0; i < 5; i++){
for(int j = 0; j < 5; j++){
m[i][j] = count++;
}
}
int **p = m;
int (*k)[5] = m;
printf("%p\t%p\t%p", *p, *k, *m);
return 0;
}
that's what has been printed:
0x100000000 0x7ffff1fc9d70 0x7ffff1fc9d70
I'm really confused why dereference *p is 0x100000000, shouldn't it be 0x7ffff1fc9d70?
You’re thinking that m is of type int **, right?
It’s not. If you had done this, it would be:
int *m[5];
That make an array of five pointers to int, so m would be pointer to pointer to int.
However, if you do this:
int m[5][5];
You get enough space for 25 ints, which the compiler will access as a 5x5 two-dimensional array. p points to the beginning of that array. Dereference it, and the compiler reads the beginning of that array and interprets it as a pointer to int. Change the numbers you’re filling it with, and you’ll get different pseudo-pointers.
code:
int arr[5] = {1,2,3,4,5};
int (*p)[5] = &arr;
printf("p:%p\n",p);
printf("*p:%p\n",*p);
result: p = *p = arr = 0x7ffee517c830 they are all the address of the array
The right way to use p to visit arr[i] is *(*p+i)
The type of pointer p is int(*)[5], so p point to an array which type is int [5]. But we can't say that p point to an invisible shell of arr, p is a variable after all. It stores the address of arr, which is also the address of arr[0], the first element of arr.
I thought *p will get me 1, which is the first element of arr.
The dereference operation means take the value in p as address and get the value from this address. Right?
So p stores the address of arr,which is 0x7ffee517c830 here, and 1 is stored in this address. Isn't **p illegal? The first dereference give us 1, and second dereference will use 1 as address which is illegal.
What I am missing?
The result of *p is an lvalue expression of array type. Using (*p) is exactly the same as using arr in any expression you could now think of.
For example:
&*p means &arr
**p means *arr (which is legal).
(*p)[i] means arr[i].
sizeof *p means sizeof arr.
Arrays are not special in this regard. You can see the same phenomenon with int x; int *q = &x;. Now *q and x have exactly the same meaning.
Regarding your last paragraph, I think you are confusing yourself by imagining pointers as glorified integers. Some people teach pointers this way but IMO it is not a good teaching technique because it causes the exact confusing you are now having.
If you dereference an int(*)[5] you get an int[5] and that's all there is to it. The data type matters in dereferencing. It does not make sense to talk about "dereferencing 0x7ffee517c830". Again this is not peculiar to arrays; if you dereference a char ***, you get a char ** etc.
The only way in which arrays are "different" in this discussion is what happens if you try to do arithmetic on them, or output them, etc. If you supply an int[5] as a printf argument for example, there is implicit conversion to int * pointing at the first of those 5 ints. This conversion also happens when applying the * operator to an int[5], which is why you get an int out of that.
p is declared as a 'pointer to int[5]'.
arr is declared as an 'int[5]`
so the initializer p = &arr; is not really that strange. If you substituted any primitive type for int[5] you wouldn't bat an eye.
*p is another handle on arr. so (*p)[0] = 1.
This really only comes up in wierd cases. It's most natural where you dereference the pointer-to-array using the subscript operator. Here's a contrived example where I want to pass a table as argument.
#include <stdio.h>
int print_row_range(int (*tab) [2], int first, int last)
{
int i;
for(i=first; i<= last; i++)
{
printf("{%d, %d}\n", tab[i][0], tab[i][1]);
}
}
int main(int argc, char *argv[])
{
int arr[3][2] = {{1,2},{3,4},{5,6}};
print_row_range(arr,1,2);
}
This example treats the table as an array of rows.
Dereferencing doesn't give you a value. It gives you an object, which can be used as a value of its type if it can be converted to.
*p, being identical to arr, is an object of an array of 5 ints, so if you want to get an integer from the array, you must dereference it again like (*p)[3].
Consider a bigger example:
int arr[5][5];
int (*p)[5] = arr;
Now you get arr[0] with *p, which itself is an array of 5. Here comes the difference:
*( p+1) == arr[1];
*(*p+1) == arr[0][1];
^ ^^^
Got the point?
One use case is to be able to allocate with malloc an 2D (or more) pointer of arrays with only one malloc:
#include <stdio.h>
#include <stdlib.h>
static int (*foo(size_t n))[42] {
return malloc(sizeof *foo(0) * n);
// return malloc(sizeof(int [n][42]); works too
}
int main(void) {
size_t n = 42;
int (*p)[42] = foo(n);
if (!p) {
return 1;
}
printf("p:");
int accu = 0;
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < sizeof *p / sizeof **p; j++) {
p[i][j] = accu++;
printf(" %d", p[i][j]);
}
}
printf("\n");
free(p);
}
I think this very funny.
One more with VLA:
#include <stdio.h>
#include <stdlib.h>
static void *foo(size_t elem, size_t n, size_t m) {
return malloc(elem * n * m);
}
int main(void) {
size_t n = 42;
int (*p)[n] = foo(sizeof **p, n, n);
if (!p) {
return 1;
}
printf("p:");
int accu = 0;
for (size_t i = 0; i < n; i++) {
for (size_t j = 0; j < sizeof *p / sizeof **p; j++) {
p[i][j] = accu++;
printf(" %d", p[i][j]);
}
}
printf("\n");
free(p);
}
Hi I'm new to the C language, can someone explains what ** symbol mean.
typedef struct _TREENODE {
struct _TREENODE *Left, *Right;
TCHAR key[KEY_SIZE];
LPTSTR pData;
} TREENODE, *LPTNODE, **LPPTNODE;
If x is a pointer, *x dereferences it. **x is the same as *(*x), so **x dereferences a pointer to a pointer. (eg, it is the thing that is pointed to by the thing that x opints to).
** is a pointer to pointer, it is also used for dereferencing a pointer variable.
eg: int a=10,*b,**c;
b=&a;
c=&b;
printf("the a value is:%d\n",a);
printf("the b value is:%d\n",*b);
printf("the c value is:%d\n",**c);
just execute this code you will get the idea about pointer to pointer.
In you want to change a variable, you pass it by pointer (to the variable).
And if you want to change a pointer, you also pass it by pointer (to the pointer) which is a double pointer.
There are two things to know about * in C:
It's an operation. Doing *x on a pointer dereferences that pointer. Doing **x on a pointer can dereference a pointer to a pointer, and so on.
It's a type. Declaring a type of int *x means that it's a pointer to an int type. Declaring int **x means that it's a pointer to a pointer to an int type.
Example:
int main() {
int foo = 4;
int *bar = &foo; // declaring a pointer to int type *bar
int **baz = &bar; // declaring a pointer to a pointer to int type **baz
printf("foo: %d, *bar: %d, **baz: %d\n", foo, *bar, **baz); // derefencing the pointer *bar and **baz
return 0;
}
In a declaration, ** means pointer to a pointer. When evaluating an expression, ** dereferences a pointer to a pointer.
int** p; // Declares p to be a pointer to a pointer.
And...
**p = 10; // Dereferences p and assigns 10 to a memory location.
One common use of pointers to pointers is to represent dynamic 2D arrays. For example, if you want to create a matrix of M rows and N columns, you could do:
int** matrix = malloc(M*sizeof(*matrix));
int i = 0, j = 0;
for ( i = 0; i < M; ++i )
matrix[i] = malloc(N*sizeof(*matrix[0]));
Usage of the double pointer:
for ( i = 0; i < M; ++i )
for ( j = 0; j < N; ++j )
matrix[i][j] = 0; // Assigns a value to the element
// at the i-th row and j-th column.
If you want to use string pointer dereferencing, you would use:
for ( i = 0; i < M; ++i )
for ( j = 0; j < N; ++j )
*(*(matrix+i)+j) = 0;
Memory allocated for the matrix has to be freed in two passes also.
for ( i = 0; i < M; ++i )
free(matrix[i]);
free(matrix);
** means a pointer to a pointer.
Most of the time I like to think of it as "pointer(s)" to "a memory area". Which in fact may be a little redundant.
For example, suppose you have to dynamically store several words on memory, how would you do that? There are several ways to do this, but I'll provide an example that illustrate the use of **.
Now, suppose you want to store three words: hi, hello and goodbye
hi, hello and goodbye are strings, they consume, 2, 5 and 7 bytes on memory respectively. Well, in fact it's 3, 6 and 8 bytes because of the \0, but lets not get into many details.
But one thing is clear, we need three memory areas to hold these strings and also three pointers to reference these memory areas later.
Note that one can just declare three pointers that points to these memory areas, but, would you be willing to declare one thousand pointers to hold one thousand words? This is where ** kicks in.
Example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUMBER_OF_WORDS 3
int
main(int argc, char **argv)
{
int i;
char **words;
/* pointers */
words = malloc(sizeof(char*)*NUMBER_OF_WORDS);
/* memory areas*/
words[0] = strdup("Hi");
words[1] = strdup("Hello");
words[2] = strdup("Goodbye");
for(i=0; i < NUMBER_OF_WORDS; i++)
printf("%d) %s\n", i, words[i]);
for(i=0; i < NUMBER_OF_WORDS; i++)
free(words[i]); /* memory area */
free(words); /* pointers */
return 0;
}