当前位置: 首页 > 知识库问答 >
问题:

C/C故意超出范围索引[复制]

艾晋
2023-03-14

假设我有一个这样的数组:

int val[10];

我故意用从负值到高于9的任何值对它进行索引,但不使用任何方式产生的值。这是出于性能原因(也许在数组访问完成后检查输入索引更有效)。

我的问题是:

  1. 这样做安全吗,或者我会遇到某种内存保护障碍,有可能破坏内存或某些索引的类似功能吗

共有3个答案

后星河
2023-03-14

正如verbose所说,这会产生未定义的行为。接下来是更精确的一点。

5.2.1/1表示

[...] 表达式E1[E2]与*((E1)(E2))相同(根据定义)

因此,val[i]相当于*((val)i))。由于val是一个数组,因此在执行加法之前会发生数组到指针的转换(4.2/1)。因此,val[i]相当于*(ptri),其中ptr是设置为

然后,5.7/2解释了ptri所指的内容。它还说(重点是我的):

[...]如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则计算不应产生溢出;否则,行为是未定义的。

ptri的情况下,ptr是指针操作数,结果是ptri。根据上面的引文,两者都应该指向数组中的一个元素,或者指向超过最后一个元素的元素。也就是说,在OP的情况下,ptr i是所有i=0。。。,10。最后,*(ptr i)是为0定义的

编辑:

我对val[10](或者相当于*(ptr 10))是否会产生未定义的行为感到困惑(我认为C不是C)。在某些情况下,这是正确的(例如,int x=val[10];是未定义的行为),但在其他情况下,这一点并不清楚。例如,

int* p = &val[10];

正如我们已经看到的,这相当于int*p=

我找到了这两个参考资料,显示了这个问题有多模糊:

我可以用数组结束元素后面的地址吗?

通过下标:C标准是否合法,取一个超过结束数组元素的地址?

越景天
2023-03-14

这是未定义的行为,你实际上可能会与优化器发生冲突。

想象一下这个简单的代码示例

int select(int i) {
    int values[10] = { .... };

    int const result = values[i];

    if (i < 0 or i > 9) throw std::out_of_range("out!");

    return result;
}

现在从优化器的角度来看:

>

值[i]i是一个索引,因此i位于[0,9]中。

if(i)

因此,由优化器重写的函数:

int select(int i) {
    int values[10] = { ... };

    return values[i];
}

有关基于开发人员没有做任何被禁止的事情这一事实的假设向前和向后传播的更有趣的故事,请参阅每个C程序员应该知道的关于未定义行为的内容:第2部分。

编辑:

可能的解决方法:如果您知道将从-M访问N,您可以:

  • 用适当的缓冲区声明数组:int值[M 10 N]
  • 抵消任何访问:值[M i]

魏勇军
2023-03-14

这是未定义的行为。根据定义,undefined的意思是“任何事情都可能发生”你的代码可能会崩溃,它可以完美地工作,它可以在所有人类之间带来和平与和谐。或者我不会赌最后一秒。

 类似资料:
  • 问题内容: 因此,我正在编写一个简单的程序来输入字符串并计算总数。的米 所以,这是我的代码 where 和str是我接受过的字符串,但是此错误不断出现 这是什么错误以及如何将其删除? 问题答案: 字符串,有效索引从0到n-1; 更改 至

  • 问题内容: 我已经开始处理我的第一个Java程序,它是一个简单的计算器,但是我得到一个错误,声称我的数组超出范围。我尝试对其进行调试,以了解这样做的原因和原因,并遵循纸上的代码,两者均显示了我期望和期望的结果。因此,我看不到问题出在哪里。代码不完整。 根据调试器,此行出现错误: 这是我当前拥有的代码的主要部分: 这是我收到的错误消息: 问题答案: 当等于中的最后一个元素索引时,则将大于最后一个元素

  • 我有一个bean,我用它作为传输对象。bean的类定义为- 我正在使用这个bean,在带有Model属性注释的Spring控制器中。对于JSP,我有JSTL。我已经用这样的字段填充了JSP。 当我提交表单时,我得到Java . lang . indexoutofboundsexception:Index:0,Size: 0。

  • 所以我创建了这个注释: 但当我运行它时,我得到了这个异常: 无法为映射设置参数:ParameterMapping{Property='name',mode=in,javatype=class java.lang.String,JDBCType=varchar,NumericScale=null,ResultMapid='null',JDBCTypeName='null',Expression='n

  • 我正在编写一个打开文本文件并检查注释的程序。然后它解析注释以检查某些单词。 im出现的错误是以下while循环检查当前行是否以空白或“/”以外的任何字符开头(如果存在非反斜杠字符),然后while循环移到下一行并再次检查。一旦while循环满足其要求并爆发,程序就会崩溃,我会得到以下输出错误。 下面是有问题的代码示例 谢谢你的帮助。我肯定这是一个简单的错误,但我就是没看到。

  • 问题内容: 嗨,我编写了Java代码来查找由其他单词组成的最长单词。我的逻辑是从文本文件中读取单词列表,并将每个单词添加到一个数组中(在文本中,单词被排序,并且每行中只有一个单词)之后,我们检查数组中的每个元素是否具有其他元素作为子字符串。如果是这样,我们计算子字符串的数量。具有最大子串数的元素将是结果 当我给一个只有两个单词的文本文件时,代码正在运行。但是,当有两个以上的单词时,我将出现以下错误