プログラムには 2 つの問題があります。
まず、あなたが言うとき:
char *cmd1[20] = {NULL};
cmd1
への 20 個のポインターの配列ですchar
。これはcmd1[i]
for i
in [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]
は 型なので、 に aをchar *
渡しています。したがって、あなたの宣言:char **
parse_command
parse_command(char *inTempString);
間違っている場合は、次のことを行う必要があります。
parse_command(char **inTempString);
あなたの呼び出しに合わせて。parse_command()
これは、が の複数の値を解析することを前提としていcmd1
ます。その場合は、要素の数も に渡す必要がありますcmd1
。これは、要素の数がparse_commnd()
わからないためcmd1
です。
2 番目の問題は、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
、および
&
アドレスオブ ( ) 演算子のオペランドとして使用する場合
より正確に言うと、オブジェクト コンテキストでは配列の名前はポインターに分解されず、値コンテキストではポインターに分解されます。詳しくはこちらをご覧ください。
では、2 番目の問題をどのように修正すればよいでしょうか。それは依存します — でメモリを動的にparse_command()
割り当てて、そのメモリを に割り当てるcmd1[0]
か、関数で作成することができtempString
static
ます。static
関数が戻ったときに関数内の変数は破棄されないため、変数へのポインターを引き続き使用できます。動的割り当てはより多くの作業です。割り当ての失敗を心配する必要があり、完了したらポインターを解放することを忘れないでください。 array の方が簡単ですが、別の呼び出しにより配列が上書きされ、一般性が低下する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 */
}