【问题标题】:Strange behavior by setting NULL in array通过在数组中设置 NULL 的奇怪行为
【发布时间】:2022-01-16 15:49:23
【问题描述】:

当我试图在 c 中的字符串数组(char 数组)的末尾设置一个 NULL 值时,我有一个奇怪的行为。我需要使用 execv 将参数传递给进程,并且我的所有参数都是 int 类型的,所以我试图获取一个字符串数组,其中所有参数都转换为 char 数组。我创建了一个返回这个字符串数组的函数,但是当我将数组的最后一个值设置为 NULL(在参数中有一个终止值)时,我丢失了存储在第二个位置的值。如果我删除 NULL 值,则不会发生任何问题。这是代码,希望有人能帮助我

char **getParams(int offset, short isNode, int first) {

    printf("Get params\n");

    int args = 8;
    int totalSize = 0;
    int tmp[args];

    tmp[0] = sizeof(char) * 5; // user / node
    tmp[1] = snprintf(NULL, 0, "%d", x);
    tmp[2] = snprintf(NULL, 0, "%d", x2);
    tmp[3] = snprintf(NULL, 0, "%d", x3);
    tmp[4] = snprintf(NULL, 0, "%d", x4);
    tmp[5] = snprintf(NULL, 0, "%d", x5);
    tmp[6] = snprintf(NULL, 0, "%d", x6);
    tmp[7] = snprintf(NULL, 0, "%d", x7);

    int i = 0;
    for (i = 0; i < args; i++) totalSize += tmp[i];

    char **_pars = malloc(totalSize + sizeof(NULL));
    
    i = 0;
    for (i = 0; i < args; i++) _pars[i] = malloc(tmp[i]);
    
    _pars[0] = isNode == 1 ? "aaaa" : "bbbb" ;
    sprintf(_pars[1], "%d", x);
    sprintf(_pars[2], "%d", x2);
    sprintf(_pars[3], "%d", x3);
    sprintf(_pars[4], "%d", x4);
    sprintf(_pars[5], "%d", x5);
    sprintf(_pars[6], "%d", x6);
    sprintf(_pars[7], "%d", x7);
    printf("Value: %s", _pars[1]); /// Print without problem value
    _pars[8] = NULL;   //// ,--- Here happens the issue
    printf("Value: %s", _pars[1]); /// Doesnt print any value

    return _pars;
}

我也尝试将它放在 for 其中我 malloc 数组位置之后,但没有结果

_pars[8] = malloc(sizeof(NULL));

【问题讨论】:

    标签: c char printf sizeof


    【解决方案1】:

    你所有的分配都是错误的。

    首先你要创建一个8元素的数组,所以第一次分配应该是

    char **_pars = malloc(8 * sizeof *_pars);
    

    或者,如果您希望数组被空指针终止,您需要分配9 元素(将8 替换为上面的9)。

    其次,snprintf 返回的大小包含空终止符,所以您的所有调用

    _pars[i] = malloc(tmp[i]);
    

    应该是

    _pars[i] = malloc(tmp[i] + 1);
    

    以适应空终止符。


    另一方面,如果您将所有 x 值放在一个数组中,您的所有代码都可以大大简化:

    int exes[8] = { x, x2, x3, x4, x5, x6, x7 };
    

    因为那时你可以对所有重复代码使用循环:

    for (unsigned i = 1; i < 8; ++i)
    {
        tmp[i] = snprintf(NULL, 0, "%d", exes[i]);
    }
    

    【讨论】:

    • 您好,非常感谢您的回答,真的很有帮助。但是我不明白你说char **_pars = malloc(8 * sizeof *_pars); 是什么意思,如果我通过正确分配它来更改totalSize(通过使用+ 1 来适应空终止符)不是一回事吗?如果我没有为单个参数定义大小,我不明白如何使用 sizeof (*_pars)
    • @EmmeDeveloper totalSize 中的大小是字符串本身的大小(不包括八个空终止符),而不是数组 _pars 的元素数。将_pars 视为一个指针数组(相当于char *_pars[8];),这样会更有意义。
    • 哦,好的,谢谢,我尝试分配 totalSize 以使用更少的内存,但我忘记了数组的每个元素必须具有相同的大小,所以我不能使用 totalSize 但我需要一个元素的大小* 数组中的元素数。非常感谢
    【解决方案2】:

    _pars 被假定为一个指向 char 的指针数组,这意味着

    _pars = malloc(args * sizeof(char*));
    

    但是你为字符串分配内存,指针应该指向。

    【讨论】:

      猜你喜欢
      • 2013-09-02
      • 2014-08-08
      • 1970-01-01
      • 2012-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-16
      相关资源
      最近更新 更多