c - C 中悬空指针和字符数组的问题

标签 c pointers dangling-pointer

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;
}

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

最佳答案

您的程序有两个问题。

首先,当你说:

char *cmd1[20] = {NULL};

cmd1 是一个由 20 个指向 char 的指针组成的数组。这意味着 [0,20) 中 icmd1[i] 是指向 char 的指针。

C 中有一条规则,规定将数组传递给函数只会将指向数组第一个元素的指针传递给函数。即,如果您有如下代码:

int ai[20];
f(ai);

那么函数调用f(ai);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 */
}

cmd1[0] 赋值中的 tempString 实际上是 &tempString[0],即指向第一个元素的指针临时字符串。但由于 tempString 一旦函数返回就被销毁,因此指针变得无效。您稍后无法使用该值。

事实上,在 C 语言中,数组的名称在所有情况下都会衰减为指向其第一个元素的指针,除了:

  • 当用作 sizeof 运算符的操作数时,并且
  • 用作地址 (&) 运算符的操作数时

更准确地说,在对象上下文中,数组的名称不会衰减为指针,而在值上下文中,它会衰减为指针。请参阅this了解更多详情。

现在,您应该如何解决第二个问题?这取决于您可以在 parse_command() 中动态分配内存,并将该内存分配给 cmd1[0],或者您可以创建 tempString函数中的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 */
}

关于c - C 中悬空指针和字符数组的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2360589/

相关文章:

java - Java 'pointers' 是整数吗?

c - 如何在原始套接字上启用卸载

c++ - 放大鼠标,考虑相机翻译? (OpenGL)

c++ - 如何从内存中删除指针并稍后在 C++ 中恢复它们

c++ - 临时对象的成员函数的左值引用返回是悬挂引用吗?

c++ - 是否可以在其范围之外访问局部变量的内存?

c - C 中的悬空指针

c++ - 如何在 C++ 中启动具有管理员权限的应用程序?

无法使用 pure64 更改 cr3 寄存器以指向新的 pml4 方向

c++ - char* p=NULL, cout<<p;给出异常(exception)