What am I doing wrong here with passing a char array to a function and in the function giving each index memory (using malloc()), then inserting something from the keyboard using gets().
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
void test(char *arr[]);
int main(){
char *arr[2];//2 is the rows
/* arr[0] = malloc(80);//This commented code works
arr[1] = malloc(80);
strcpy(arr[0], "hey");
strcpy(arr[1], "whats up");
*/
test(*arr);
printf("in array[0]: %s", arr[0]);
printf("in array[1]: %s", arr[1]);
return 0;
}
void test(char *arr[]){
int index;
char *input = malloc(80);
for(index = 0; index < 2; index++){
arr[index] = malloc(80);
gets(input);
strcpy(arr[index], input);
//arr[0] = input;
}
}
Just a very basic program which for some reason I am having trouble with. Also one more question When I declare an array what is the difference between these forms
char *array
as oppose to
char *array[size]
or
char **array
Thanks, Kevin
You declare arr
as char *arr[2]
. You then pass in *arr
, which has type char*
to test. But test expects a char *[]
. So that won't work. You should simply pass in arr
as it is, ie test(arr)
.
char * array
is a pointer to character, typically used to point to the first character in an array of characters, ie a string. char **array
is a pointer to pointer to character. Typically used to represent an array of strings. char *array[size]
is mostly equivalent to the one above, but it unlike, that one, the top-level pointer is already pointing at a valid array, so the array does not need to be malloc
ed.
By the way, your test
function could be simplified a bit: the strcopy
is unneccessary.
void test(char *arr[])
{
int i;
for(i=0;i<2;i++)
{
arr[i] = malloc(80);
gets(arr[i]);
}
}
OK, in C declarations, you only get the first thing allocated that you read from a declaration.
This is a bit obscure until you understand how to read a declaration.
Operators have precedence, and that precedence applies in a declaration. For simplicity, take:
() - Either raises precedence, or means "function taking parameters and returning..."
[] - Array of
* - Pointer to (right associative)
So, the declaration:
char *a[3];
is an "array of 3 pointers to char", whereas
char (*a)[3];
is a "pointer to arrays of 3 char" (a pointer to rows of a multi-dim char array with row width 3)
The compiler allocates the very first thing on the stack. So, in the first example, you get three pointers that are capable of pointing to (an as yet unallocated) chars.
| ptr | --> (unallocated char)
| ptr | --> (unalloc char)
| ptr | --> (unalloc char)
in the second:
| ptr | --> (unallocated block of 3 char)
the next rule is: If you have a pointer, you have an array. So in both cases, you end up with multi-dimensional arrays.
In the first, the number of rows is fixed (you already allocated it), but each row can have a different size, as the compiler knows the pointer can be offset by a char to get to the next char.
In the second, you have a fixed row size, but the compiler knows how to offset your base pointer (by 3 chars each), so you have any number of rows.
C is also a call-by-value language. So, if you've declared a variable:
char *a[3];
then 'a' by itself is "an array of 3 ptr to char", but a[0] is "a ptr to a char", and a[0][0] is a char.
When you write a function that expects:
void f(char *arg[]) {
...
}
you must pass it an array of pointers to char. It does not care how many rows there are (you have to keep track of that)...it only cares that the type is correct.
So, if you have 'a' declared as in our first example, you have to call f(a). A function call does an assignment-like thing to the function args:
f(a) means call f with (arg = a).
The precedence rules are especially important, and you should work on these until you can read declarations like this:
int (*f(int (*a)[4], void (*f)()))[6];
which is "f is a function that takes:
- a pointer to arrays of 4 int
- a pointer to a function that takes nothing and returns nothing)
and (then f) returns a pointer to arrays of 6 int".
char *array creates a pointer to bytes of memory. char *array[size] creates a pointer to arrays of length 'size'. char **array is just a pointer to a pointer to bytes of memory
So as you can see, the problem with your code is that you are trying to pass the test function something it doesn't expect. The test function wants a pointer to a pointer, you just give it a pointer. The correct passage would be: test(arr);
To put the second one into perspective: you see this when making command line programs (sort of).
consider the following code:
#include<stdio.h>
int main(int argc, char *argv[]) {
printf("%s\n", argv[0]);
return 0;
}
The argv pointer points to the command line arguments, each of which are a string (which is a just a pointer, or an array). So lets say you did the following for Linux:
./some_program -option opt-input
Each of these are treated as their own string. char *argv[] points to each string. The first printf will print out ./some_program, because this is the first string that argv points to.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.