ISO/IEC 9899:2011 6.7.6.3 Semantics 7 是什么意思?

What is ISO/IEC 9899:2011 6.7.6.3 Semantics 7 means?

首先,这里是原文(ISO/IEC 9899:2011 6.7.6.3语义7):

A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. If the keyword static also appears within the [ and ] of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.

为了更好的理解这个问题,我写了一些代码:

#include <stdio.h>

void f(int a[static 10][10])
{
    printf("0x%p\n", a);
}

int main(int argc, char *argv[])
{
    int a[][10] = {[20] = {1, 2}};
    f(a);
    int b[][10] = {{3, 4}};
    f(b);
    return 0;
}

static(int a[static 10][10]) 代表什么?
该代码的行为是否未定义?为什么?
为什么我们只需要提供对数组第一个元素而不是所有元素的访问?

what is that static(int a[static 10][10]) stand for?

正如您提供的报价中所写:

... If the keyword static also appears within the [ and ] of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.

Is the behavior of that code undefined? why?

是的,如果函数需要一个在大小表达式中具有指定数量元素的数组,但数组类型的相应参数具有较少的元素,则函数的行为将是未定义的,因为该函数将尝试访问内存超出数组中用作参数的元素数。

Why do we only need to provide access to the first element of an array not all of it?

我们至少需要提供对大小表达式中参数声明中指定数量的元素的访问,因为它是函数与函数用户之间的契约。该函数至少需要大小表达式中指定的元素数。

限定符的目的是让编译器知道它可以在闲暇时生成读取数组任何部分的代码,而不管是否需要它。作为何时可能有用的示例,请考虑以下内容:

int get_first_positive_of_four(int arr[static 4])
{
  if (arr[0] > 0) return arr[0];
  if (arr[1] > 0) return arr[1];
  if (arr[2] > 0) return arr[2];
  if (arr[3] > 0) return arr[3];
  return 0;
}

有些处理器有一条指令,可以以比重复的单次读取更快的方式将内存的多个字读入寄存器。例如,在 ARM7-TDMI 上(有点过时的架构,但其指令时序很容易推断),一条将一个字加载到寄存器的指令需要 3 个周期,而加载 N 个字的指令需要 2+N 个周期。因此,用一条指令加载所有四个字将花费与执行两个单独的加载相同的时间。如果编译器要无条件地加载所有四个字,则此代码将比在仅使用第一个值的情况下使用单独加载的版本花费更长的时间,如果使用两个值则需要相同的时间,如果使用三个则需要更少的时间或使用四个值。

如果向函数传递了一个位于可访问内存末尾的双项数组,并且其第二个值为正,则行为将在没有静态限定符的情况下定义,但是预加载所有四个值的代码版本可能会陷入内存错误。因此,如果没有 static 限定符,该优化将无效,但会有效。

我不知道编译器在多大程度上利用了这个限定符,但它允许编译器生成代码,推测性地读取可能最终需要或可能不需要的数据,这可能比如果禁止对此类数据进行推测性读取。