How Do you pass a pointer-to-an-array to a function? - c

How do you pass an array to a function where that function can edit it's contents?
like when doing
function(int *x)
{*x = 10;}
main()
{int x;
function(&x);}
how could i do the same using a character array?
whenever I do
function(char *array[], int *num)
{ int x = *num;
*array[x] = 'A'; }
main()
{ char this[5] = "00000"; //not a string
int x = 3;
function(&this, &x); }
DEV C++ says
[Warning] passing arg 1 of `function' from incompatible pointer type
obviously I did something wrong, so please tell me how to fix that. Thanks :D

You should write:
void function(char array[], int *num)
{
int x = *num;
array[x] = 'A';
}
void main()
{
char my_array[5] = "00000";
int x = 3;
function(my_array, &x);
}
Notation char *array[] is an array of pointers that you do not need here.
When you pass an array somewhere, you should not take its address. Arrays are adjusted to pointers by default.
EDIT:
Function prototypes:
void function(char array[], int *num);
void function(char *array, int *num);
are absolutely identical. There is no even minor difference between them.

Since arrays can only be passed by address, you don't really want a char * array here, just a char array:
rettype function(char *array, int *num)
{
array[*num] = 'A';
}
int main()
{
char arr[] = "1234567890";
int i = 2;
function(arr, &i);
}

In C, array names "devolve" to a pointer to the head of the array, by passing "&array", you're passing a pointer to a pointer to the head of the array, thus the warning.
char array[512];
myfunc(array, foo);
is the proper way to do what you want.

Actually you have taken one dimension array. So you can define function in two ways...
(i)
function(char array[], int *num)
{ int x = *num;
*array[x] = 'A'; }
main()
{ char this[5] = "00000"; //not a string
int x = 3;
function(this, &x); }
and
(ii)
function(char *array, int *num)
{ int x = *num;
*array[x] = 'A'; }
main()
{ char this[5] = "00000"; //not a string
int x = 3;
function(this, &x); }
But in your function definition, you wrote *array[] as argument which means the array is two dimensional array. So you should declare array as two dimensional array.
function(char *array[], int *num)
{ int x = *num;
//implement your code }
main()
{ char this[5][10];
// you can initialize this array.
int x = 3;
function(this, &x); }
I think it will be helpful to you.

Okay, the first thing to remember is that there's no such thing as a pointer "to an array" although you'll hear that said fairly often. It's sloppy.
(As pointed out below, the terminology "pointer to an array" does strictly have a meaning -- but I maintain that you've been confused by it. What really happens is that every pointer contains an address. Depending on the declaration, the compiler can identify if it's being used correctly in context, and that's what your error message is really telling you: what you declared in the function is a pointer to an array of chars, which is to say the same thing as a char **, instead of a char *, which is what you're passing. But char *, or char **, or char ******, the important point is that you're making it too complex -- you already have the address you need identified by the array name.)
Pointers is pointers, they're addresses.
An array in C is simply an allocated chunk of memory, and it's name represents the address of the first element. So
char a[42];
is a block of memory 42 char's long, and a is its address.
You could rewrite your second function as
void foo(char* a, int num){ // (3)
// notice that you don't need the word function and
// for lots of reasons I wouldn't use it as a function name.
a[num] = 'A'; // (4)
}
int main(){
// Sadly "00000" IS a string no matter what your comment
// says. Use an array initializer instead.
char arry[5] = {'0','0','0','0','0' } ; // (1)
foo(arry,3); // (2)
}
This does what I believe your code means to do. Note that
(1) Since "00000" really is a string, it's actually creating an array 6 elements long which could have been initialized with the array initializer
{'0','0','0','0','0', 0 }
(2) The array (which I named 'arry' instead of 'this' since 'this' is often a keyword in C-like languages, why risk confusion?) is already an address (but not a pointer. It can be on the right-hand side of an assignment to a pointer, but not on the left hand side.)
So when I call
foo(arry,3);
I'm calling foo with the address of the first element of arry, and the number 3 (you don't need to declare a variable for that.)
Now, I could have also written it as
foo(&arry[0],3);
You would read that as "find the 0-th element of arry, take its address." It is an identity in C that for any array
char c[len];
the expression c and &c[0] refer to the same address.
(3) that could also be defined as foo(char arry[], int num). Those are equivalent.
(4) and when you refer to a[num] you're referring directly to the num-th element of the memory pointed to by a, which is at the address of the start of the array arry. You don't need all that dereferencing.
Don't be disturbed that this is a little hard to follow -- it's tough for everyone when they start C.

Firstly dont use this as a variable name, its a C++ keyword. Sorry didnt realise it was a C question.
main()
{
char foo[5] = "00000"; //not a string
int x = 3;
function(foo, &x);
}
You dont take the memory address of foo. foo when used in a pointer-accepting context degrades into a pointer to the first element. *foo is the same as foo[0] which is the same as *(foo + 0)
like wise foo[3] is the same as *(foo + 3) (the compiler takes care of multiplying the element size).

Related

how to copy returned array directly into another array?

I have been learning arrays, but theres one thing that I cant figure out.
I borrowed two books for C and looked online, but found no solution.
My function timesTen multiplies every array elemenet that I have by 10,
then returns pointer of that array back function main()
How can I copy array a[2] directly in array x[2]?
I would usually use for loop, but I cant, because arguments are in two different functions.
Solution has probably got something to do with pointers, so feel free to post sollution here, but is there any way around them aswell?
Heres the source code:
#include <stdio.h>
int timesTen(int a[])
{
int i;
for (i=0;i<2;i++)
{
printf("%d\t", a[i]);
a[i]*=10;
printf("%d\n", a[i]);
}
return a;
}
int main()
{
int i;
int x[2];
int a[2]={10,50};
// i know here's an error, but how do I fix it? I cant put x[0]=timesTen(a[0])
x[2] = timesTen(a);
//also what if there is array a[10], and I want to copy it in x[5]
for (i=0;i<2;i++)
printf("%d\n", x[i]);
return 0;
}
Thanks!
What you need to understand is the distinction between arrays and pointers. When you declare your two arrays in main(), you allocate two times memory for two integers. That's fine. But in C, you simply cannot pass arrays around (as in: implicitly allocate a new slap of memory and copy the data of the source array into this memory region). Instead, any array identifier will decay to a pointer to the first element of the array in almost all situation. So when you write
int x[2];
int a[2]={10,50};
timesTen(a);
this code is precisely equivalent to
int x[2];
int a[2]={10,50};
timesTen(&a[0]);
So, why does that not clash with your declaration of timesTen()? Because array parameters in function declarations decay right there, on the spot, into a pointer! So, your function declaration is precisely equivalent to this one:
int timesTen(int* a) {
This is one of the least understood features of the C language, and admittedly, it is hard to wrap your brain around this, but once you understand what pointer decay means, you will be much more at ease using pointers and arrays.
So, back to your question. Since you passed only a pointer to your array to timesTen(), and since you modify this array, the changes are directly visible in main(). There are two ways to achieve the behavior you want:
You can change the definition of timesTen() to copy the data into a destination array:
void timesTen(int size, int* source, int* dest) {
for(int i = 0; i < size; i++) dest[i] = 10*source[i];
}
int main() {
int x[2];
int a[2]={10,50};
timesTen(2, a, x); //pointer decay!
//x now contains {100, 500}
}
You can copy the data into the destination array before calling your function to modify the destination array:
void timesTen(int size, int* data) {
for(int i = 0; i < size; i++) data[i] = 10*data[i];
}
int main() {
int x[2];
int a[2]={10,50};
memcpy(x, a, sizeof(a)); //the sizeof operator is one of only two places where no pointer decay happens!
timesTen(2, x); //pointer decay!
//x now contains {100, 500}
}
In the function timesTen, since a is an array, each modification made to it in the function is also done to the parameter you passed (call by address not by value). Therefore you don't need to returns anything.
void timesTen(int a[])
{
int i;
for (i=0;i<2;i++) a[i]*=10;
}
And you just call it by:
timesTen(a);
You probably want something like this:
timesTen(a);
memmove(x, a, 2 * sizeof(x[0]));
instead of
x[2] = timesTen(a);
Note that your function does not need to return anything, because it is modifying the array on its original place. In C if you have an array parameter, it means that only a pointer is passed, not the whole array.
in main function:
int *p;
int i;
p = timesTen(a);
for ( i = 0; i < 2; i++ )
{
printf( "%d\n",*(p + i)); // here you can print the values returned from your function
}
Through pointers you could have eaisly managed it
main ()
{
int a[ 2 ];
int *ptr = timesTen(a);
for ( int i=0; i<2 ; i++)
{
printf("%d",ptr[i]);
}
And as far as
x[2] = timesTen(a);
Is concerned note that x[2] will give "value at 2nd adress from adrees of base that is x"
And it is not a variable but it is a value and you cant assign to a value.
Technically x[2] is not a lvalue.

statically allocated array as function argument in C

Can I do this in C:
void myFunc(int *vp) {
// do some stuff with vp
}
int main() {
int v[5] = {1,2,3,4,5};
myFunc(v);
return 0;
}
I mean, what would be the correct? myFunc(&v); ?
Thanks!!
Arrays decay to pointers when you pass them as arguments. However, array decay is not the same as taking the address of an array.
"Decay" is how some types are transformed when passed as function arguments. Even though v's type is int [5], it becomes int* when you pass it to a function. This is a behavior a lot of people don't like, but there's nothing to do about it.
Note that, on the other hand, the type of &v is int (*)[5], that is, a pointer to an array of 5 integers. This type doesn't decay, that is, it doesn't transform automatically into another type if you pass it as a function parameter (and that's also why it wouldn't work if you used it in your example, since you need a pointer to integers, not a pointer to an array of integers).
The "correct" thing to do (assuming decay is OK) is to do myFunc(v), just as you're doing in your snippet. Keep in mind that you lose array bounds information when you do it.
Yes ... Your code is correct.
Here v==&v[0] array name is equal to address of first element of array
myFunc(v);
passing array name as argument that means you are passing address of first element in array.
void myFunc(int *vp)
Here you are using pointer. which store the address of first element of array which is passed so you can access the block which is covered with the array.by incrementing the pointer location.
And
myFunc(&v);
&v==&&v[0];
&v is address of address of array first element.
Now
void myFunc(int *vp)
Here You got address of address of array first element, This is not pointing to array. Instead pointing some memory location.Now You can't access the array by incrementing the pointer.
Your code is correct It will work....
But you should take extra care to check the boundary condition.
Please look through the code.
void myFunc(int *vp) {
vp[5] = 30;
}
int main() {
int v[5] = {1,2,3,4,5};
int a = 10;
printf("Value of a before fun call %d\n", a);
myFunc(v);
printf("Value of a before fun call %d\n", a);
return 0;
}
similarly
void myFunc(int *vp) {
vp[5] = 30;
myFunc2(vp);
}
void myFunc2(int *vp) {
vp[6] = 30;
}
int main() {
int v[5] = {1,2,3,4,5};
int a = 10;
printf("Value of a before fun call %d\n", a);
myFunc(v);
printf("Value of a before fun call %d\n", a);
return 0;
}
This will result in segmentation fault due to stack curruption. Since local variables are in stack.

Confusing pointers and arrays in C

I'm trying to understand the mistake in the following code. The code is supposed to switch between two arrays.
What I saw is that it switches only the first 4 bytes. Is the following correct?
Passing &num1 or num1 is the same (both pass the address of the first element in the array).
The (char**) casting is wrong. That's because when you pass and array you pass the address it's laid in. So you actually pass here a void*.
How can I actually switch between these two arrays only by pointers? Is thatpossible?
I know it is possible if from the beginning I had defined char **num1 and char **num2. But I want it to stay with the array notation!
#include <stdio.h>
void fastSwap (char **i, char **d)
{
char *t = *d;
*d = *i;
*i = t;
}
int main ()
{
char num1[] = "hello";
char num2[] = "class";
fastSwap ((char**)&num1,(char**)&num2);
printf ("%s\n",num1);
printf ("%s\n",num2);
return 0;
}
Passing &num1 or num1 is the same (both pass the address of the first element in the array). Am I correct?
No. The first one is a pointer to the array itself (of type char (*)[6]), whereas in the second case, you have a pointer to the first element (of type char *; an array decays into a pointer to its first element when passed to a function).
The (char*) casting is wrong
Indeed, you are casting a char (*)[6] to a char **.
So you actualy pass here a void (Am i correct?).
No. Non sequitur. I don't see how the void type is relevant here. You have pointers, arrays, and eventually pointers to arrays.
Arrays are not pointers. Your code is trying to swap arrays, which does not make sense, since assignment to arrays is not permitted. What you probably want is
I. either get pointers to the first character of each string, and then swap the pointers themselves, like this:
void swap_pointers(const char **a, const char **b)
{
const char *tmp = *b;
*b = *a;
*a = tmp;
}
const char *p1 = "hello";
const char *p2 = "world";
swap_pointers(&p1, &p2);
II. Or use actual arrays, and you swap their contents:
void swap_contents(char *a, char *b, size_t n)
{
for (size_t i = 0; i < n; i++) {
char tmp = a[i];
a[i] = b[i];
b[i] = tmp;
}
}
char a1[] = "hello";
char a2[] = "world";
swap_contents(a1, a2, strlen(a1));
Also, you may want to read this.
1. Passing &num1 or num1 is the same (both pass the address of the first element in the array)
Not true, &num1 gives you a pointer to a pointer that points to the entire character string "hello" (char*[6]) while num1 is just a pointer to the character block "hello" (char[6]).
2. The (char*) casting is wrong. That's because When you pass and array you pass the address it's laid in. So you actualy pass here a void (Am i correct?).
It is still not a void, it's just a pointer to a character pointer. If it were void, then it would be perfectly valid to do something like void** myVoid = &num1. This will cause a syntax error unless you explicitly typecast your char** to a void** before you assign it.
The problem is your explicit type casting &num1 as a char** which is not correct, it is a char*[6]. But of course, you can't declare a variable as a char*[6] so it can't be used in this way. To fix it you need to declare your num1 and num2 as:
char* num1 = "hello";
char* num2 = "class";
instead and keep everything else the same. In fact, with this change there is no need to typecast your &num1 as a char** because it already is that.

What does (*ptr)[10] mean?

void main()
{
int (*d)[10];
d[0] = 7;
d[1]=10;
printf("%d\n",*d);
}
It should print 10 but compiler is showing error such as follows:
test.c:4:7: error: incompatible types when assigning to type ‘int[10]’ from type ‘int’
Note that I have included some errors , not all.
As noted by chris, d is a pointer to an array. This means you use the variable improperly when you access it, but also that you will access random memory unless you assign d to point to a valid array.
Change your program as follows:
int main(void)
{
int (*d)[10]; /* A pointer to an array */
int a[10]; /* The actual array */
d = &a; /* Make `d` point to `a` */
/* Use the pointer dereference operator (unary prefix `*`)
to access the actual array `d` points to */
(*d)[0] = 7;
(*d)[1] = 10;
/* Double dereference is okay to access the first element of the
arrat `d` points to */
printf("%d\n", **d);
return 0;
}
In C, [] is the same as *, the pointer syntax. Thus the following lines are the same:
int** array2d1;
int* array2d2[];
int array2d3[][];
To relate to a closer example, the main function has the following popular forms:
int main(int argc, char** argv){ ... }
or
int main(int argc, char* argv[]){ ... }
Thus
int (*d)[10]
is the same as
int* d[10]
which is the same as
int** d;
int firstArray[10];
d = &firstArray;
Effectively, you are creating a pointer to a pointer (which is a pointer to an array) and allocating the first pointer to an array that 10 elements. Therefore, when you run the following lines:
d[0] = 7;
d[1] = 10;
You are assigning the 1st array's address to 7 and the second array's address to 10. So as Joachim has mentioned, to assign values, you need to deference twice:
(*d)[0] = 7
(*d)[1] = 10
Which says "Assign 7 to the 0th index at the value pointed by d". I hope that makes sense?
d is a pointer to an array of 10 ints.
int (*d)[10] is the declaration for a point to an array of 10 ints.
vs.
int *d[10], which is an array of 10 int pointers.
For more complex syntax like this (usually involving pointers), I use cdecl to help me decode it.
It's used in this form
int d[10]
I guess you are mistaken that d must be a "kind of pointer" and therfor you put an * before the d.
But that's not what you want. You wan to name an array of integer and the notation for that is seen above.
Concept of pointer can get confusing sometimes in C.
Consider an array int d[6] = {0,1,2,3,4,5}
Then, *d is equivalent to d[0]. d is itself an pointer to an array and *d dereferences that pointer and gives us the value.
Hence, following code would print the same values:
int main()
{
int (d)[10];
*d = 7;
*(d + 1)=10;
printf("%d\n",*d);
printf("%d\n",d[0]);
return 0;
}
result:
7
7
Please see http://codepad.org/LYY9ig1i.
If you change your code as follows:
#include<malloc.h>
int main()
{
int *d[10]; //not (*d)[10]
d[0] = (int *)malloc(sizeof(int *) * 10);
d[0][0] = 7;
printf("%d\n",d[0][0]);
return 0;
}
Hope this helps you!

Is it possible to still address the individual elements of an array via a pointer?

I am trying to write a program that will mutliply two numbers, but output the result in binary, showing the calculation (i.e. shifting the rows). I'm storing the binary numbers as an array of 32 characters, and each element is either 1 or 0.
I have a function that will convert decimal to binary character array, but then my array only exists within the function, but I need to use the array within another function and also within main. I was thinking it might be possible to use pointers to change the value of the array in main from within my converter function, so then the array will exist in main and can be used in other functions. Is this possible?
I've declared two pointers to character arrays:
char (*binOne)[32];
char (*binTwo)[32];
if I pass the pointer as a parameter to the function, can I still access each element? Sorry if I'm not making much sense here.
In C, most of the time array behaves like pointer to its first element, so what you probably want to do is:
void foo(char* arr){
//some stuff, for example change 21-th element of array to be x
arr[20] = 'x';
}
int main(){
char binOne[32];
char binTwo[32];
// change array binOne
binOne[20] = 'a';
foo(binOne);
// now binOne[20] = 'x'
foo(binTwo);
// now binTwo[20] = 'x'
}
A continuation of what I added as a comment:
In C, if you want to modify/return an array, you'll do that by passing a pointer to it as an argument. For example:
int toBinary(char *buff, int num) { /* convert the int, return 1 on success */ }
...
char buff[32];
toBinary(buff, 9001);
In C, an array's name is it's address, it's the address of the first element:
buff == &buff == &buff[0]
Yes, this is possible. But you only need a pointer to the array not an array of pointers.
You need to prototype like
e.g.
void int_to_arr(int n, char *arr);
void arr_to_int(int *n, char *arr);
in main(){
char *binarr = calloc(32, sizeof(char));
int n = 42;
int_to_arr(n, binarr);
}
void int_to_arr(int n, char *arr)
{
//do you conversion
//access array with
// arr[i]
}
void arr_to_int(int *n, char *arr)
{
//do you conversion
//access array with
// *n = result;
}

Resources