【问题标题】:C can someone tell me what is going on here?C 谁能告诉我这里发生了什么?
【发布时间】:2023-03-12 18:57:01
【问题描述】:

我无法弄清楚这里到底发生了什么。我期望的是输出应该说键中只有1个元素,当我只分配120字节的0位置时说有7个。

void add2(char **b, char *i) {
    if (!i) {
        b[0] = (char*) malloc(120);
        sprintf(b[0], "%s", "hithere");
    } else {
        strcat(b[0], "\\\\");
        strcat(b[0], i);
    }
}

void add1(char **b) {
    add2(b, NULL);
    add2(b, "one");
    add2(b, "two");
    add2(b, "three");
}

void add() {
    char *keys[2];
    int i;
    add1(keys);
    fprintf(stderr, "%s\n", keys[0]);
    for (i = 0; keys[i]; i++)
        fprintf(stderr, "%d\n", i);
    free(keys[0]);
}

int main (int argc, char** argv)
{   
     add();
     add();
     return 255;
}

输出: 那里\一\二\三 0 1 2 3 4 5 6 7 那里\一\二\三 0 1 2 3 4 5 6 7

字符串与我预期的一样,但是我认为之后应该只打印 0,因为 0 是我添加的唯一元素。我需要能够释放每个位置,而不仅仅是 free[0],但是当我将 free[i] 放在打印出 i 的 for 循环中时,它会堆栈转储。

关于下面响应的初始化,如果我需要一个类似于 1000 而不是 2 的数组,那么如何在不输入 1,000 个 0 的情况下将它们全部初始化为 0

【问题讨论】:

    标签: c free malloc


    【解决方案1】:
    /* ... */
    void add() {
        char *keys[2];
    /* ... */
    

    keys 是一个由 2 个指向 char 的指针组成的数组,但 它没有被初始化
    试试这个

    /* ... */
    void add() {
        char *keys[2] = {0, 0}; /* explicit initialization of the two elements */
    /* ... */
    

    在所有成员都没有显式初始化器的情况下,未初始化的成员被初始化为零(其类型的正确零)。

    /* ... */
    void add() {
        char *keys[1000] = {42}; /* explicit initialize the first element to 42 */
                                 /* and implicitly initialize all other elements to 0 */
                                 /* **ATTENTION** */
                                 /* initializing a pointer to 42 is wrong */
                                 /* I only wrote that as an example */
    /* ... */
    

    编辑,引自标准

    6.7.8 初始化
    语法
    1

    初始化器:

    赋值表达式
    { 初始化列表 }
    { 初始化列表 , }

    初始化列表:

    designationopt 初始化器
    初始化器列表,指定opt初始化器

    空的初始化列表没有语法。

    【讨论】:

    • 好吧,我不知道我需要多少元素?我会做 char **keys 吗?然后使用 malloc?
    • 这和 memset(keys, '\0', sizeof(keys)) 有什么区别?
    • 你可以使用 "char *keys[SIZE] = {};"绕过输入 5 行注释
    • 我的编译器告诉我“警告:ISO C 禁止空初始化大括号”。我试图从标准中获得正确的参考,但没有找到。
    【解决方案2】:

    您尚未初始化 keys 数组,因此它包含内存中发生的任何内容。在这种情况下,keys[1] 和最多 7 个不为零。

    【讨论】:

      【解决方案3】:

      有什么区别 隐式初始化数组元素 为 0 并将它们显式设置为 0 使用 memset()?

      char *data[1000] = {0};
      memset(data, 0, sizeof data);
      

      第一个选项(隐式初始化)将数组的每个元素都设置为正确类型的零;第二个选项将所有元素的所有位(加上任何填充)设置为 0。通常(当前所有计算机的 99.99%键入 0 和 所有位 0。

      想象一台具有分段内存的计算机......其中指针由两部分组成。当您将其设置为 0(0 的正确类型)时,编译器可以使该 0 与所有位 0 不同。如果您专门将所有位设置为 0,则最终可能会得到一个无效的指针。

      void *test = 0; /* can make test something like "0xC0DE:0x0000" */
      memset(test, 0, sizeof test); /* will make test as "0x0000:0x0000" */
      

      【讨论】:

      • 他们说 99% 的统计数据都是现场制作的。 ;)
      • 对于所有整数类型(包括char),ISO C 和 C++ 实际上保证“所有位 0”是值 0(尽管反过来不正确:值 0 不必是“所有位0" - 在符号位表示的情况下,这是合法的,+0 和 -0 之一将有一位不为零)。所以做到 100%。
      【解决方案4】:

      对于第二部分的问题,

      如果您需要初始化一个类似于 1000 而不是 2 的数组,请使用以下

      char *keys[1000] = {0};
      

      如果你用一个值初始化数组的一个元素,那么数组的所有其他成员将自动初始化为零。

      即,如果您使用

      char *keys[1000] = {42};
      

      然后数组的第一个成员将被初始化为 42,而数组的所有其他成员将自动初始化为零。

      【讨论】:

      • memset(keys, '\0', sizeof(keys)) 怎么样?有什么区别吗?
      • 例如,如果它是float 的数组,则会有所不同。使用{} 将初始化为0(或0.0,或空指针值),这并不总是与所有位0 相同。
      • 另外,你不必写={0}。你可以写={}
      猜你喜欢
      • 2021-04-10
      • 2020-04-10
      • 2017-04-06
      • 2013-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-13
      • 1970-01-01
      相关资源
      最近更新 更多