【问题标题】:C : Making sure the element you return from an array is correctC:确保从数组返回的元素是正确的
【发布时间】:2009-08-02 22:18:13
【问题描述】:

假设我们有这段C 代码:

int x[] = {1, 2, 3, 4, 5};

printf("%d", *(x + 1)); //prints 2
printf("%d", *(x + 500)); //prints 7209065 (...?)

从第二次调用中可以看出,它仍然返回一些东西......但它是垃圾。

所以我问,你如何在 C 中处理这种情况?也就是说,你怎么知道返回的元素是真的存在于数组中的元素还是只是垃圾?

【问题讨论】:

  • 从你在这里发布的这个问题和其他问题来看,我真的认为你会更喜欢使用 C++ 而不是 C
  • 呵呵,我学习 C 是为了好玩(希望有一天能开始涉足电子和微控制器编程)...也就是说,我的意思是,它不是为了工作或任何东西.所以,我的计划是首先尝试尽可能多地掌握 C 的窍门,然后再转向 C++
  • @Dreas - 这听起来不无道理,要了解真正发生的事情(只要你意识到其中有一些痛苦:-)
  • 如果你想学习嵌入式 C 语言,这很公平。但是,如果 C++ 是您的最终目标,则不必在 C++ 之前学习 C。
  • 嗯,这并不是一个真正的“最终目标”……从某种意义上说,我希望能够了解 C 和 C++ 之间的区别。这就是我首先从 C 开始的主要原因。

标签: c arrays


【解决方案1】:

添加另一个保存数组长度的变量,并且无论何时要访问该数组,请确保您在数组的范围内。

【讨论】:

    【解决方案2】:

    简单地说,你不能。这只是 C 和 C++ 语言的一个特性/错误/设计。

    【讨论】:

      【解决方案3】:

      正如每个人都指出的那样,由于 C 的性质,您不能这样做。但是,您可以使用一些工具来检测您的代码,并对内存访问执行进一步检查(在开发周期中使用) )。 Purify 就是这样一种工具,我发现它对于识别此类问题非常有用。

      【讨论】:

      【解决方案4】:

      在运行时不检查数组边界。它们只是内存块,其中包含类型的指示。这是一项语言功能,它减少了代码的总开销。不管你喜不喜欢,它就是这样。

      【讨论】:

        【解决方案5】:

        一般来说,这就是创建“更智能”的数据类型的原因——比如 C++ 的 STL 数组,它会因索引越界错误而引发异常。

        【讨论】:

        • 请注意,STL 向量默认不会检查任何内容(运算符 []),除非您通过 at() 方法访问它们。
        【解决方案6】:

        C 不检查数组边界。您有责任通过与数组长度 (sizeof(x)/sizeof(x[0])) 进行比较来检查访问是否在范围内。

        【讨论】:

          【解决方案7】:

          实际上,要么是一个以 0 结尾的数组,在数组末尾有 0 并限制自己按顺序遍历它,要么将包含数组长度的变量与数组一起传递并在所有数组之前检查它访问。

          C 中的数组本质上不知道它有多长,因此您无法免费获得任何依赖于它的行为。

          【讨论】:

          • “限制自己按顺序遍历它” - 但这意味着失去 O(1) 访问权限,不是吗?
          • 在您需要检查 O(1) 访问权限的情况下,它肯定会。
          【解决方案8】:

          这也是为什么在大多数(更可靠的)使用数组的 C 库中,您会看到作为参数传递的数组的大小,例如 fread() fwrite()

          【讨论】:

            【解决方案9】:

            详细说明 JaredPar 和 Ed 的答案:

            C 数组是一块连续的内存。当你说 int x[] = {1, 2, 3, 4, 5}; C 为 5 个整数分配了足够的内存。你要求的是第 500 个元素,所以你得到的是没有正确分配给 X 的内存。这是垃圾,每次运行它都可能改变。

            我同意罗布的观点。添加一个包含 X 中元素数量的变量,然后对每个元素执行一个 for 循环。

            如果您想要在运行时改变长度的数组,有更好的方法来做到这一点。

            【讨论】:

              【解决方案10】:

              在很大程度上,将 C 视为具有“数组”类型是错误的。您使用的语法是指针周围的糖。 x[y] 真的是 *x + sizeof(something) * y 的语法糖(其中“某事”比我想要的更复杂;在这个万一某事是int)。

              请记住,C 是一种中级语言……一种“可移植程序集”,您不会带来不必要的期望。

              【讨论】:

                【解决方案11】:

                如果你足够“幸运”,或者你的指数偏差足够大,那么 你不会得到“垃圾”——你会得到一个segmentation fault。但这实际上是一件好事,因为它可以帮助你意识到你做错了什么。一些工具会告诉您发生这种情况的确切位置。

                有时这取决于程序的输入,这意味着只有在插入某些输入时才会发生段错误(例如,如果您的 '500' 值是作为用户的输入接收的)。 (那些查找和处理稍微麻烦一些)

                最有问题的情况是您确实得到“垃圾”并且“无法知道它”的情况。

                在这些情况下,首先编写好的代码确实无可替代。 但正如其他人所建议的那样,DynamicStatic analysis 工具可能会有很大帮助。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2019-02-19
                  • 2014-06-16
                  • 1970-01-01
                  • 1970-01-01
                  • 2017-04-17
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多