Есть две проблемы с вашей программой.
Во-первых, когда вы говорите:
char *cmd1[20] = {NULL};
cmd1
- это массив из 20 указателей на char
. Это означает, что cmd1[i]
для i
в [0,20) является указателем на char
.
В C существует правило, которое гласит, что передача массива в функцию только передает указатель на первый элемент массива функции. То есть, если у вас был такой код:
int ai[20];
f(ai);
тогда тип ai
в вызове функции f(ai);
равен int *
, а указатель, переданный f()
, равен &ai[0]
, первый элемент ai
.
Итак, когда вы делаете:
parse_command(cmd1);
вы сразу знаете, что "вещь", переданная в parse_command()
, является &cmd1[0]
, то есть указателем на первый элемент cmd1
. Поскольку cmd1[0]
имеет тип char *
, вы передаете char **
в parse_command
. Поэтому ваша декларация:
parse_command(char *inTempString);
неправильно, вы должны сделать:
parse_command(char **inTempString);
в соответствии с вашим звонком. Предполагается, что parse_command()
будет анализировать более одного значения в cmd1
. Если это так, вы также должны передать количество элементов в cmd1
в parse_commnd()
- так как он не может знать, сколько элементов cmd1
имеет.
Ваша вторая проблема в том, что вы не можете вернуть адрес локальной переменной из функции в C. Как и выше, помимо вызова функции, возврата массива в C или присвоения чего-либо массиву в C также делает имя массива "распадающимся" для указателя на его первый элемент.
Итак, учитывая вашу функцию:
/* changed inTempString to cmd1 because that's what you probably meant */
int parse_command(char *cmd1)
{
char tempString[256];
/* call to function that assigns a string to tempString */
cmd1[0] = tempString;
/* you need to return an int from here */
}
tempString
в присваивании cmd1[0]
на самом деле &tempString[0]
, то есть указатель на первый элемент tempString
. Но так как tempString
уничтожается, как только функция возвращается, указатель становится недействительным. Вы не можете использовать значение позже.
На самом деле, в C имя массива уменьшается до указателя на его первый элемент во всех случаях, кроме:
- при использовании в качестве операнда для оператора
sizeof
и
- при использовании в качестве операнда для оператора адреса (
&
)
Чтобы быть более точным, в контексте объекта имя массива не распадается на указатель, а в контексте значения оно распадается на указатель. См. this для получения более подробной информации.
Теперь, как вы должны исправить вторую проблему? Это зависит от & mdash; вы можете либо динамически выделять память в parse_command()
, и назначать эту память для cmd1[0]
, либо вы можете сделать tempString
static
в функции. Поскольку static
переменные в функции не уничтожаются при возврате функции, вы можете продолжать использовать указатель на нее. Динамическое распределение - это больше работы - вам нужно беспокоиться о сбое выделения и помнить, чтобы освободить указатель, когда закончите. static
массив проще, но вы должны быть осторожны, потому что другой вызов parse_command
перезапишет массив, делая его менее универсальным.
Предполагая, что вы хотите пойти по пути "динамической памяти", вот схема, которую вы можете использовать:
#include <stdio.h> /* printf */
#include <stdlib.h> /* malloc and free */
int main(void) /* main returns int */
{
char *cmd1[20] = {NULL};
/* number of commands. "sizeof cmd1" is the number of bytes
used by the cmd1 array, and "sizeof cmd1[0]" is the number
of bytes used by one element of the array. The division
gives you the number of elements. This is 20 of course
but doing it this way makes sure that changing "20" to any
number works. */
size_t ncmds = sizeof cmd1 / sizeof cmd1[0];
/* pass the number of commands to "parse_command", since
it can't know otherwise */
int x = parse_command(cmd1, ncmds);
int i;
for (i=0; i < x; ++i) {
printf("%s ", cmd1[i]);
free(cmd1[i]);
}
return 0; /* return a value from main */
}
int parse_command(char **cmd1, size_t ncmds)
{
char *tempString; /* we will malloc this */
int i; /* the number of mallocs done successfully */
tempString = malloc(...);
if (tempString == NULL) {
/* failure, handle gracefully */
} else {
++i; /* make sure i doesn't exceed or equal ncmds */
}
cmd1[0] = tempString;
/* do the above as many times as you need */
return i; /* the number successfully assigned to */
}