pointer to array in C : Address Arithmetic and Array Assignment - c

I have following pointer to array variable.
int (*p)[3];
int a[3] = { 1,2,3 } ;
int b[3] = { 11,22,33 } ;
int c[3] = {111,222,333} ;
I want to store these 3 array into variable p. How i have to allocate the memory for p
and How should i store these 3 array into p like array of pointer. Whether is this possible ...? and How..?
Note:
p = (int (*)[])malloc(3); Now this p is capable of pointing three
integer array which size 3 . How i have to assign these a,b,c to this
p ?
.

You don't need to allocate memory, it's allocated when you declare your array of pointers. Each pointer should point to the memory already allocated, but a, b, c are allocated automatically/statically, so you don't need to worry about that. Just assign them to the members of the array p and you're done.
If p is a pointer to array, then code should be:
int **p = malloc(sizeof(int*)*3);
...
p[0] = a; p[1] = b; p[2] = c;
...
free(p); /* when done*/
Declaring int *p[3] creates array of pointers, not pointer to array.
edit
If you want a pointer to an array then you can do this:
int a[3];
int *p = a;
And don't forget - you can use a on its own as a pointer to array it represents, where needed, you don't need a separate variable.

int* p[3];
int a[3] = { 1,2,3 } ;
int b[3] = { 11,22,33 } ;
int c[3] = { 111,222,333} ;
p[0] = a;
p[1] = b;
p[2] = c;
That's it.
Edit 1
A pointer to array ?
int** p;
int a[3] = { 1,2,3 } ;
//...
p = &a;
Edit 2
And a array of pointers to array of int :
int** p[3];
int a[3] = { 1,2,3 } ;
//...
p[0] = &a;
//...

Related

How to assign Pointer to an Array, to a new Array?

I got this code:
#include <stdio.h>
#include <string.h>
int main(void)
{
int a[3]={1,2,3},
b[3];
int (*p)[3]= &a;
b = p;
for(int i=0;i<3;i++)
printf("%i",b[i]);
}
-I wanted output to be like "123", but I am having problems assigning the b array to what the p is pointing.
ps -
memcpy( b, p, sizeof(b)); does just what i want but i want to do it without the use of that function.
The line
b = p;
has a couple of problems. First of all, array expressions may not be the target of the = operator; you can't assign an entire array in a single operation like that1.
Secondly, the types don't match; p has type int (*)[3], while b has type int [3]. Arrays are not pointers - array expressions "decay" to pointer expressions under most circumstances, but in this case even the pointers would be of incompatible types (b would decay to an expression of type int *, not int (*)[3]).
No, the only ways to copy the contents of one array to the other are to use library functions like memcpy or to use a loop to assign each element individually:
for ( size_t i = 0; i < 3; i++ )
b[i] = (*p)[i]; // or b[i] = a[i]
That's it.
Initialization is different from assignment.
Arrays do not have the assignment operator. You need somehow to copy elements of one array to another array.
Without using the standard function memcpy you can use an ordinary loop as for example
for ( size_t i = 0; i < sizeof( a ) / sizeof( *a ); i++ )
{
b[i] = a[i];
}
Or if to use intermediate pointers you can write
for ( int *p = a, *q = b; p != a + sizeof( a ) / sizeof( *a ); ++p )
{
*q++ = *p;
}
You have a small fixed size array, perfectly suitable for wrapping inside a struct, so you can do this:
#include <stdio.h>
#include <string.h>
struct ia3 {
int data[3];
}
int main(void)
{
struct ia3 a = {{1,2,3}};
struct ia3 b;
struct ia3 *p = &a;
b = *p; // struct assignment
for(int i=0;i<3;i++) {
printf("%i",b.data[i]);
}
}
"...but i want to do it without the use of [memcpy(,,)]."
It is unclear why using memcpy() is not agreeable in this exercise, but it does do the task more efficiently then loop for large array sizes.
If you just want a pointer to the array...
int a[3] = {1,2,3};
//create pointer
int *b = a;//does not copy array a, just points to it
//If an additional array is needed, do this...
int b[3] = {0};
int i = 0;
//to copy, without memcpy(), use this alternative.
for(i=0; i<3; i++) b[i] = a[i];//makes copy of array a
for(i=0;i<3;i++)
printf("%i", b[i]);

Assigning address of pointer to pointer-to-pointer

I am trying to make a simple piece of c code using pointers work but memory is being overwritten unexpectedly.
I want to create an array of pointers to integers then create a pointer to an integer and assign it's address to an array.
Therefore, the array will point to a pointer to an integer. I did this in a function called add_value_to_array().
Here is my code :
void add_value_to_array(int *** array, int * value) {
*array = &value;
}
int main() {
int ** arr = { 0 };
int value = 5;
int * value_ptr = &value;
add_value_to_array(&arr, value_ptr);
//arr = &value_ptr;
printf("looool\n");
printf("looool\n");
printf("looool\n");
printf("looool\n");
printf("%p\n", arr[0]);
}
What I want is :
arr -> value_ptr -> 5
(arr = &value_ptr
*array = value_ptr
value_ptr = &value
*value_ptr = 5
**arr = 5)
however, this is what I have right after add_value_to_array() is called, but memory is overwritten when I call the printfs(), I get garbage values in my arr variable.
Even weirder, if I do directly arr = &value_ptr instead of calling add_value_to_array, things go as expected and memory is not overwritten by the printfs().
So it seems that memory is allocated differently if I use a function or if I do I do things outside of it.
What is happening that I am seeing this behavior?
Following assumption: You want to create an array of length 1 (maybe greater length later) of pointers to int. And you want that single pointer in the array to point to the local variable named 'value'.
Then:
int* arr[] = { 0 }; // or { NULL }, if you prefer
// ^ creates an array; either you specify size explicitly or it will be deduced
// from initializer, as in this case
Arrays automatically decay to pointer to first element, if you pass them to a function. So:
add_value_to_array(arr, &value);
// ^ decays to pointer
// ^ here you still need a pointer; you can create it directly, though
Little problem left: arr decaying to pointer is of type int**. You need the same type in your function:
void add_value_to_array(int** array, int* value)
// ^ one asterisk less
{
*array
// ^ this one is NOW correct: array points to the first element of arr
// dereferencing gives you exactly this element, i. e. the pointer
= /* & */value;
// ^ must be dropped: you already have a pointer and you assign it to
// another one, which is fine.
}
Be aware that pointers simply are addresses of variables somewhere in memory. A bit simplified:
int n = 10;
int* p0 = &n;
int* p1 = &n; // p1 and p0 point both to the same variable n
int* p2 = p0; // now again p2 points to n
*p0 = 12; // change the value pointed to
printf("%d\n", *p2); // will print 12, as both pointers point to the same address.
Function parameters do not differ in this respect, they are just ordinary variables. And it doesn't play a role if the pointee is a data value or a pointer itself:
int n = 10;
int m = 12;
int* p = &n;
int** p1 = &p; // pointer to pointer to int
int** p2 = p1; // both p1 and p2 point to p
*p1 = &m; // re-assign the POINTER
printf("%d\n", **p2); // again prints 12:
// p1 and p2 both point to p which was reset to m, though...
Thank you all for your answers, this helped me find the bug :
I had to pass my value_ptr by address and not by value.
Here is my corrected code :
void add_value_to_array(int *** array, int ** value_ptr) {
*array = value_ptr;
}
int main() {
int ** arr = { 0 };
int value = 5;
int * value_ptr = &value;
add_value_to_array(&arr, &value_ptr);
//arr = &value_ptr;
printf("looool\n");
printf("looool\n");
printf("looool\n");
printf("looool\n");
printf("%p\n", arr[0]);
}
Thank you all for your help !

array of pointers pointing the same variable

Can all the pointer members of an array point to the same variable?
ex: What happens when *a[i] is pointed to a variable C of value 5 and the length of the array is 3? Will a[0],a[1],a[2] have the values 5?
Yes, based on this answer
If all pointers are of the same type, there is no issue
int a = 10;
int *b[3];
b[0] = &a;
b[1] = &a;
b[2] = &a;
a = 5; // now b[0-2] are also equal 5.
No a[0],a[1],a[2] will not point to variable C, you have to explicitly make them point to variable C. Consider below example.
#include<stdio.h>
void main()
{
int *a[3];
int c=5;
a[0] = &c;
printf("%d %d %d", *a[0],*a[1],*a[2]);//this will print 5 junkvalue junkvalue
a[1] = &c;
a[2] = &c;
printf("%d %d %d", *a[0],*a[1],*a[2]);//this will print 5 5 5
}

Pointer to an array and Array of pointers

As I am just a learner, I am confused about the above question. How is a pointer to an array different from array of pointers? Please explain it to me, as I will have to explain it to my teacher. Thank you.
Pointer to an array
int a[10];
int (*ptr)[10];
Here ptr is an pointer to an array of 10 integers.
ptr = &a;
Now ptr is pointing to array of 10 integers.
You need to parenthesis ptr in order to access elements of array as (*ptr)[i] cosider following example:
Sample code
#include<stdio.h>
int main(){
int b[2] = {1, 2};
int i;
int (*c)[2] = &b;
for(i = 0; i < 2; i++){
printf(" b[%d] = (*c)[%d] = %d\n", i, i, (*c)[i]);
}
return 1;
}
Output:
b[0] = (*c)[0] = 1
b[1] = (*c)[1] = 2
Array of pointers
int *ptr[10];
Here ptr[0],ptr[1]....ptr[9] are pointers and can be used to store address of a variable.
Example:
main()
{
int a=10,b=20,c=30,d=40;
int *ptr[4];
ptr[0] = &a;
ptr[1] = &b;
ptr[2] = &c;
ptr[3] = &d;
printf("a = %d, b = %d, c = %d, d = %d\n",*ptr[0],*ptr[1],*ptr[2],*ptr[3]);
}
Output:
a = 10, b = 20, c = 30, d = 40
Background
Think of pointers as just a separate data type. They have their own storage requirements -- such as their size -- they occupy 8 bytes on a x86_64 platform. This is the case of void pointers void*.
In those 8 bytes the information stored is the memory address of another piece of data.
The thing about pointers is that since they "point" to another piece of data, it's useful to know what type that data is too so you can correctly handle it (know its size, and structure).
In stead of having their own data type name such as pointer they compose their name based on the data type they refer to such as int* a pointer to an integer. If you want a plain pointer without type information attached to it you have the option of using void*.
So basically each pointer (to int, to char, to double) is just a void* (same size, same use) but the compiler knows the data being pointed to is of type int and allows you to handle it accordingly.
/**
* Create a new pointer to an unknown type.
*/
void* data;
/**
* Allocate some memory for it using malloc
* and tell your pointer to point to this new
* memory address (because malloc returns void*).
* I've allocated 8 bytes (char is one byte).
*/
data = malloc(sizeof(char)*8);
/**
* Use the pointer as a double by casting it
* and passing it to functions.
*/
double* p = (double* )data;
p = 20.5;
pow((double* )data, 2);
Pointer to array
If you have an array of values (let's say integers) somewhere in memory, a pointer to it is one variable containing its address.
You can access this array of values by first dereferencing the pointer and then operating some work on the array and its values.
/**
* Create an array containing integers.
*/
int array[30];
array[0] = 0;
array[1] = 1;
...
array[29] = 29;
/**
* Create a pointer to an array.
*/
int (*pointer)[30];
/**
* Tell the pointer where the data is.
*/
pointer = &array;
/**
* Access the data through the pointer.
*/
(*pointer)[1] = 999;
/**
* Print the data through the array.
* ...and notice the output.
*/
printf("%d", array[1]);
Array of pointers
If you have an array of pointers to values, the entire array of pointers is one variable and each pointer in the array refers to somewhere else in the memory where a value is located.
You can access this array and the pointers inside it without dereferencing it but in order to reach a certain value from it you will have to dereference one of the pointers inside the array.
/**
* Create an array containing pointers to integers.
*/
int *array_of_pointers[30];
array_of_pointers[0] = 0;
array_of_pointers[1] = 1;
...
array_of_pointers[29] = 29;
POINTER TO AN ARRAY
Pointer to an array will point to the starting address of the array.
int *p; // p is a pointer to int
int ArrayOfIntegers[5]; // ArrayOfIntegers is an array of 5 integers,
// that means it can store 5 integers.
p = ArrayOfIntegers; // p points to the first element of ArrayOfIntegers
ARRAY OF POINTERS
Array of pointers will contain multiple pointers pointing to different variables.
int* ArrayOfPointers[2]; // An array of pointers which can store 2 pointers to int
int A = 1;
int B = 2;
int *PointerToA ;
PointerToA = &A ; // PointerToA is a pointer to A
int *PointerToB ;
PointerToB = &B ; // // PointerToA is a pointer to A
ArrayOfPointers[0] = PointerToA ; // ArrayOfPointers first element points to A
ArrayOfPointers[1] = PointerToB ; // ArrayOfPointers second element points to B
An array of pointers is this - int* arr[3]; will contain multiple pointers pointing to 3 different variables
Pointer to an array is this - int (*arr)[3]; will point to first element of an array of 3 elements
Below is a sample code which might help you more
int array[3];
array[0] = 1;
array[1] = 2;
array[2] = 3;
int* point = array; // pointer of an array
int* points[3];
points[0] = &array[0];
points[1] = &array[1];
points[2] = &array[2]; // an array of pointer
I'm not sure if i get the question right but I will try to point this out.
There are pointers pointing to a type
e.g.:
int num;
int* p_num = &num; // this is pointing at the int
Moreover there are arrays (which in fact are pointers)
int num; // an Integer
int* p_num; // a pointer. (can point at int's)
int arr[3]; // an Array holding 3 int's
arr[0] = 1; // + holding the values 1, 2, 3
arr[1] = 2;
arr[2] = 3;
p_num = arr; // because an array is just a pointer "p_num" num is now pointing at
// + the first element in the array.
// + ** THIS IS NOW A POINTER TO AN ARRAY **
num = *p_num;// num = 1
And there are arrays, which can hold multiple pointers:
int num1;
int num2;
int num3;
int* p_array[3]; // an array holding 3 pointer to int's
p_array[0] = &num1; // this is pointing at num1
p_array[1] = &num2; // num2, ...
p_array[2] = &num3;
// ** THAT IS AN ARRAY OF POINTERS **
I often resort to pen and paper when thinking about c pointers.
Pointer to an array
[a] -> [b]
[c]
[d]
.
.
.
An array of pointers
[a] -> [j]
[b] -> [k]
[c] -> [l]
. .
. .
. .
A pointer to an array contains the memory location of an array. Whereas an array of pointers contains lots of memory locations, which contain single values (or possibly other arrays, or arrays of pointers ;).
Pointer to an array
#include <stdio.h>
#include <stdlib.h>
void main(void) {
int i;
int *ptr, *loopPtr;
ptr = malloc(10 * sizeof(int)); // allocate an array of 10 ints on the heap
loopPtr = ptr; // copy pointer into temp pointer
for(i=0; i < 10; i++) {
*loopPtr = i; // dereference pointer and store i in it
loopPtr++; // move pointer to next memory location
}
loopPtr = ptr; // copy pointer into temp pointer
for(i=0; i < 10; i++)
printf("%d, ",*(loopPtr++)); // move across array printing
printf("\n");
free(ptr); // free memory allocated on the heap
}
An array of pointers
#include <stdio.h>
#include <stdlib.h>
void main(void) {
int i;
int *ptr[10]; // an array of pointers
// allocate 10 ints on the heap pointed to by an array
for(i=0; i < 10; i++)
ptr[i] = malloc(sizeof(int));
for(i=0; i < 10; i++)
*ptr[i] = i; // dereference pointer and store i in it
for(i=0; i < 10; i++) // iterate through array and dereference pointers
printf("%d, ",*ptr[i]);
printf("\n");
for(i=0; i < 10; i++)
free(ptr[i]);
}
The best way to contrast the difference is probably with the malloc() calls, one returns a pointer to an array of 10 ints and the other returns 10 pointers to individual ints.

How to pass by reference a sub-array which is in a dynamically allocated 2D array?

I need to pass by reference sub-arrays which are part of a dynamically allocated 2D array. I have tried the following approach, which doesn't seem to work. Any ideas if it is possible?
void set1(int *a){
a = malloc(2*sizeof(int));
a[0] = 5;
a[1] = 6;
}
void set2(int *a){
a = malloc(2*sizeof(int));
a[0] = 7;
a[1] = 8;
}
int main(){
int **x = malloc(2*sizeof(int*));
set1(x[0]);
set2(x[1]);
return 0;
}
You need to pass the address of your sub-arrays, like in this example:
void set(int ** a)
{
*a = malloc(2 * sizeof(int));
(*a)[0] = 4;
(*a)[1] = 9;
}
int main(void)
{
int ** x = malloc(2 * sizeof(int*));
set(&x[0]);
set(&x[1]);
}
Whenever you have a function that needs to modify something in the caller's scope, you need a de­re­fe­rence in the function (like our *a) and an address-of in the caller (like &x[0]).
(Your code, by contrast, assigns the pointer to allocated memory to a local variable (namely myArray), which is lost when the function returns. And the memory is lost along with it.)
#include <stdlib.h>
#include <stdio.h>
void testFunc1(int** a){
*a = malloc(2*sizeof(int));
(*a)[0] = 5;
(*a)[1] = 6;
}
void testFunc2(int** a){
*a = malloc(2*sizeof(int));
(*a)[0] = 7;
(*a)[1] = 8;
}
int main(){
int** x = malloc(2*sizeof(int*));
set1(&x[0]);
set2(&x[1]);
printf("value:%d\n", x[0][0]);
printf("value:%d\n", x[0][1]);
printf("value:%d\n", x[1][0]);
printf("value:%d\n", x[1][1]);
return 0;
}
Output:
value:5
value:6
value:7
value:8
Visualize the workings:
x --> x[0] | x[1]
| |
\/ \/
? ?
You want to change the adress where x[0] (x[1]) is pointing to. For the function being able to change that for real, you have to pass x[0] (x[1]) as a reference. Since x[0] (...) is a pointer to int ( i.e. int* ), the argument of the function should be a pointer to a pointer to int ( i.e. of type int** ) to accomplish this ( in C ). Accordingly we call set1 with the address of x[0]. In set1 we want to store the address returned by malloc at the address we get as an argument. So we dereference it and do exactly that.

Resources