【问题标题】:Looping a fixed size array without defining its size in C循环一个固定大小的数组而不在 C 中定义它的大小
【发布时间】:2010-12-30 11:41:47
【问题描述】:

开始提问的一些示例代码:

 #define FOO_COUNT 5

 static const char *foo[] = {
       "123",
       "456",
       "789",
       "987",
       "654"
 };

这通常会被迭代,例如,如下所示:

int i = FOO_COUNT;
while (--i >= 0) {
 printf("%s\n", foo[i]);

在没有明确让人类数 5 的情况下,是否可以执行上述操作?将来我可能会添加/删除元素并忘记更新数组的大小,从而破坏我的应用程序。

【问题讨论】:

    标签: c loops


    【解决方案1】:
    int i = sizeof(foo)/sizeof(foo[0]);
    

    【讨论】:

    • 如果 foo 中的字符指针指向可变大小的字符串,这仍然有效吗?
    • 所以如果任何元素超过15个字符,这个检查会失败吗?那么使用 NULL 哨兵可能更好吗?再次感谢。
    • 不会失败。 sizeof[foo[0]) ==> sizeof(char*);字符数无关紧要。
    • 好的,不确定您在上面的评论中的 15 个字符限制指的是什么
    • 评论的 15 个字符限制部分意味着他只是添加了额外的字符以满足 Stack Overflow 中 cmets 的 15 个字符的最小值。他的回答只是“是”,但 Stack Overflow 不喜欢这么短的 cmets。
    【解决方案2】:

    最后使用一个标记,比如NULL:

    static const char *foo[] = {
           "123",
           "456",
           "789",
           "987",
           "654",
           NULL
    };
    
    for (char *it = foo[0]; it != NULL; it++)
    {
            ...
    }
    

    【讨论】:

      【解决方案3】:

      执行此操作的通常方法是用 NULL 结束数组并迭代,直到你命中。

      【讨论】:

        【解决方案4】:

        是的。

        int i = sizeof(foo) / sizeof(char*);
        

        注意:这只适用于静态分配的数组。它不适用于malloced 或newed 数组。

        【讨论】:

          【解决方案5】:
          size_t i = sizeof foo / sizeof *foo; // or sizeof foo / sizeof foo[0]
          

          这将 foo 数组 (sizeof foo) 中的总字节数除以单个元素 (sizeof *foo) 中的字节数,得到数组中的元素数。

          【讨论】:

            【解决方案6】:

            C99 中还有另一种方法,特别是如果您想要命名索引,允许例如本地化等。

            enum STRINGS {
              STR_THING1,
              STR_THING2,
              STR_THING3,
              STR_THING4,
              STR_WHATEVER,
            
              STR_MAX         /* Always put this one at the end, as the counting starts at 0 */
                              /* this one will be defined as the number of elements */
            }     
            
            static const char *foo[STR_MAX] = {
              [STR_THING1]   = "123", 
              [STR_THING2]   = "456",
              [STR_THING3]   = "789",
              [STR_THING4]   = "987",
              [STR_WHATEVER] = "OR Something else",
            };
            

            通过使用命名初始化程序,即使枚举值发生变化,程序仍然是正确的。

            for (i = STR_THING1; i<STR_MAX; i++)
              puts(foo[i]);
            

            或程序中具有命名索引的任何地方

              printf("thing2 is %s\n", foo[STR_THING3]);
            

            此技术可用于模拟资源包。声明一个enum 和几个带有语言变体的字符串数组,并在程序的其余部分使用一个指针。简单而快速(尤其是在 64 位机器上,获取常量(字符串)的地址可能相对昂贵。 编辑:sizeof foo/sizeof *foo 技术仍然适用于此。

            【讨论】:

              【解决方案7】:

              是的。

              sizeof(foo)/sizeof(char*)

              是 5。

              【讨论】:

                【解决方案8】:

                对于某些应用程序,tryCatch 会起作用。

                【讨论】:

                • 即使 C 有 trycatch,我看不出它们与遍历数组有什么关系。
                猜你喜欢
                • 2012-03-17
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-10-29
                • 2010-12-21
                • 2011-07-09
                相关资源
                最近更新 更多