2
main(){
   char *cmd1[20] = {NULL};
   int x = parse_command(cmd1);
   printf("%s\ ",cmd1[0]);
}

parse_command(char *inTempString){
   char tempString[256];
   (call to function that assigns a string to tempString)
   cmd1[0] = tempString;
}

cmd1[0]打印出inside时出现问题main。我很确定这是一个悬空指针错误。我真的不知道如何修复它。

4

5 回答 5

4

There are two issues with your program.

First, when you say:

char *cmd1[20] = {NULL};

cmd1 is an array of 20 pointers to char. This means that cmd1[i] for i in [0,20) is a pointer to char.

There is a rule in C that says that passing an array to a function only passes the pointer to the first element of the array to the function. I.e., if you had code like:

int ai[20];
f(ai);

then the type of ai in the function call f(ai); is int * and the pointer passed to f() is equal to &ai[0], the first element of ai.

So, when you do:

parse_command(cmd1);

you immediately know that the "thing" passed to parse_command() is &cmd1[0], i.e., a pointer to the first element of cmd1. Since cmd1[0] is of type char *, you are passing a char ** to parse_command. Therefore, your declaration:

parse_command(char *inTempString);

is wrong, you should do:

parse_command(char **inTempString);

to match your call. This assumes that parse_command() will parse more than one value in cmd1. If that is the case, you should also pass the number of elements in cmd1 to parse_commnd()—since it can't know how many elements cmd1 has.

Your second problem is that you can't return the address of a local variable from a function in C. As above, in addition to a function call, returning an array in C, or assigning something to an array in C also makes the name of an array "decay" to a pointer to its first element.

So given your function:

/* 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 */
}

the tempString in the assignment to cmd1[0] is actually &tempString[0], i.e., a pointer to the first element of tempString. But since tempString is destroyed as soon as the function returns, the pointer becomes invalid. You can't use the value later.

In fact, in C, the name of an array decays to a pointer to its first element in all cases, except:

  • when used as an operand to sizeof operator, and
  • when used as an operand to the address-of (&) operator

To be more precise, in object contexts, the name of an array doesn't decay to a pointer, and in value contexts, it decays to a pointer. See this for more details.

Now, how should you fix your second issue? It depends—you can either allocate memory dynamically in parse_command(), and assign that memory to cmd1[0], or you can make tempString static in the function. Since static variables in a function are not destroyed when a function returns, you can continue using a pointer to it. Dynamic allocation is more work—you need to worry about allocation failure and you need to remember to free the pointer when done. static array is easier, but you have to be careful because another call to parse_command will overwrite the array, making it less-generic.

Assuming you want to go the "dynamic memory" route, here is a scheme that you could use:

#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 */
}
于 2010-03-02T03:24:00.813 回答
0

您在 main 中将 cmd1 声明为 char** - 即指向 char 指针的指针。但是,然后您将其传递给 parse_command,您已将其定义为采用 char*; 指向 char 的指针。

这只编译是因为指针到任何东西的自动转换为指针到字符。这是旧版本 C 的历史产物,它使用 'char*' 代替 'void*';在您的情况下,这仅意味着编译器忽略了您所做的类型错误,而不是向您报告。

于 2010-03-02T02:53:48.430 回答
0

是的,你不能那样做。

char tempString[256];

在函数的堆栈上声明一个变量parse_command,该变量超出范围,parse_command返回时指向它的指针不再有效。

您需要在堆上分配命令字符串,以便parse_command返回时仍然有效。这是一种方式。

parse_command(char *inTempString){
   char tempString[256];
   (call to function that assigns a string to tempString)

   int cb = strlen(tempString)+1;
   cmd1[0] = (char *)malloc(cb);
   strcpy(cmd1[0], tempString);
}

您还应该free(cmd[0])在主退出之前调用。

除此之外,此代码无法编译。您不能cmd1[0]parse_command函数内部引用。当您尝试传入时,您应该会遇到类型不匹配cmd1parse_command如果您的意思是从那里返回一个 char*,parse_command那么它应该被声明为将一个 char** 作为参数,更像这样。

parse_command(char **pcmd){
   char tempString[256];
   (call to function that assigns a string to tempString)

   int cb = strlen(tempString)+1;
   pcmd[0] = (char *)malloc(cb);
   strcpy(pcmd[0], tempString);
}
于 2010-03-02T02:54:14.420 回答
0

像这样的东西会起作用:

parse_command(char **inTempString){
        static char tempString[256];
        strcpy(tempString,"some string you want to copy");
        inTempString[0] = tempString;
}
  • 在您的代码中,一旦函数返回, tempString 将不存在。即使在函数返回后,您也需要让它保持活动状态。您可以动态分配空间并稍后取消分配,也可以将其声明为静态。
  • 您还需要将类型参数 inTempString 从 char* 更改为 char**。
于 2010-03-02T02:58:15.160 回答
0

您正在cmd1尝试mainparse_command.

我会说至少cmd1[0]看起来像一个整数,因为它没有用该方法声明。

cmd1声明为,array of char*但方法的参数char*可能是 apointer to char array不是 pointer to array of char*

将 char 数组复制到另一个 char 数组的最佳方法是使用或类似的方法memcpystrcpy这些方法接受指向要复制的 src、dest 和 size 的指针。

于 2010-03-02T02:58:31.613 回答