Zif*_*ion 19
计算在运行时完成.
负指数不一定必须导致违规,并且有其用途.
例如,假设您有一个指针,该指针当前指向数组中的第10个元素.现在,如果您需要在不更改指针的情况下访问第8个元素,则可以使用负索引-2轻松地执行此操作.
char data[] = "01234567890123456789";
char* ptr = &data[9];
char c = ptr[-2]; // 7
Run Code Online (Sandbox Code Playgroud)
Eri*_*hil 11
这是一个使用示例.
无限脉冲响应滤波器部分地根据最近的先前输出值计算.通常,会有一些输入值数组和一个放置输出值的数组.如果当前输出元素是y i,则y i可以被计算为y i = a 0 ·x i + a 1 ·x i-1 + a 2 ·y i-1 + a 3 ·y i-2.
为此编写代码的一种自然方式是:
void IIR(float *x, float *y, size_t n)
{
for (i = 0; i < n; ++i)
y[i] = a0*x[i] + a1*x[i-1] + a2*y[i-1] + a3*y[i-2];
}
Run Code Online (Sandbox Code Playgroud)
观察到i
零时,y[i-1]
并且y[i-2]
具有负指数.在这种情况下,调用者负责创建一个数组,将输出的初始两个元素设置为"起始值"(通常为零或从前一个缓冲区保留的值),并将指针传递给第一个新值的位置是要写的.因此,此例程IRR
通常接收指向数组中间的指针,并使用负索引来处理某些元素.
为什么在程序中支持这种潜在的内存违规?
因为它遵循指针算术,并且在某些情况下可能有用.
编译器不应该至少抛出一个负指数警告吗?(我正在使用GCC)
array[10]
当数组只有10个元素时,编译器在访问时不会发出警告的原因相同.因为它将这项工作留给了程序员.
或者这个计算是在运行时完成的?
是的,计算是在运行时完成的.
阐述Taymon的答案:
float arr[10];
float *p = &arr[2];
p[-2]
Run Code Online (Sandbox Code Playgroud)
现在完全可以.我没有看到负面指数的良好使用,但是如果你指向一个有效范围之外,如果它通常是不可判定的,那么为什么标准会将其排除.