C 在这个实现中是否承诺缓存失效

C 在这个实现中是否承诺缓存失效,c,caching,gcc,volatile,C,Caching,Gcc,Volatile,考虑以下代码: volatile uint32_t word; for (i=0; i<10; i++) { word = *(uint32_t *)(ADDRESS_IN_MEMORY); printf("%"PRIu32, word); some_function_compiled_in_other_object(); /* this function may or may not change memory content at adress ADDRESS

考虑以下代码:

volatile uint32_t word;
for (i=0; i<10; i++)
{
    word = *(uint32_t *)(ADDRESS_IN_MEMORY);
    printf("%"PRIu32, word);
    some_function_compiled_in_other_object();  /* this function may or may not change memory content at adress ADDRESS_IN_MEMORY */
}
volatile uint32\u t字;
对于(i=0;i
所以,由于word是易失性的,我们知道word=*(uint32_t*)(内存中的地址_)将被执行10次

没有

假设CPU有一些寄存器(只允许值在寄存器之间传输,不允许数据直接从内存中的一个位置传输到内存中的另一个位置),编译后的代码实际上执行以下操作:

    for (i=0; i<10; i++)
    {
        CPU_register_1 = *(uint32_t *)(ADDRESS_IN_MEMORY);
        word = CPU_register_1
所以,由于word是易失性的,我们知道word=*(uint32_t*)(内存中的地址_)将被执行10次

没有

假设CPU有一些寄存器(只允许值在寄存器之间传输,不允许数据直接从内存中的一个位置传输到内存中的另一个位置),编译后的代码实际上执行以下操作:

    for (i=0; i<10; i++)
    {
        CPU_register_1 = *(uint32_t *)(ADDRESS_IN_MEMORY);
        word = CPU_register_1

C标准对缓存一无所知,它们是C语言范围之外的特定于应用程序的细节

volatile
关键字只与编译器执行的优化有关。编译器需要确保对
volatile
限定变量的操作按特定顺序排序,而不是进行优化

读取硬件寄存器时,必须始终使用
volatile
,否则编译器可以假定寄存器的内容自上次使用以来从未更改过

因此,如果您的示例中的
ADDRESS\u IN_MEMORY
是一个与地址相对应的数字,那么您就有一个bug,因为您将它读作
*(uint32\u t*)(ADDRESS\u IN_MEMORY);
。这个bug与缓存内存没有丝毫关系

缓存内存处理由CPU/分支预测来处理,而不是由编译器或C语言来处理。因此,除非您访问MMU寄存器并在其中指定行为,否则无法直接从应用程序代码对其进行影响。这当然是特定于系统的。健全的系统设置不会加载内存映射硬件寄存器访问进入数据缓存


但是,您可以编写缓存友好型代码,方法是连续访问内存,始终从上到下读取下一个相邻地址,而不需要任何可以更改访问顺序的分支。

C标准对缓存一无所知。它们是C语言范围之外的特定于应用程序的详细信息

volatile
关键字只与编译器执行的优化有关。编译器需要确保对
volatile
限定变量的操作按特定顺序排序,而不是进行优化

读取硬件寄存器时,必须始终使用
volatile
,否则编译器可以假定寄存器的内容自上次使用以来从未更改过

因此,如果您的示例中的
ADDRESS\u IN_MEMORY
是一个与地址相对应的数字,那么您就有一个bug,因为您将它读作
*(uint32\u t*)(ADDRESS\u IN_MEMORY);
。这个bug与缓存内存没有丝毫关系

缓存内存处理由CPU/分支预测来处理,而不是由编译器或C语言来处理。因此,除非您访问MMU寄存器并在其中指定行为,否则无法直接从应用程序代码对其进行影响。这当然是特定于系统的。健全的系统设置不会加载内存映射硬件寄存器访问进入数据缓存


但是,您可以通过连续访问内存来编写缓存友好型代码,始终从上到下读取下一个相邻地址,而不需要任何可以更改访问顺序的分支。

您是否将
volatile
*(uint32\u t volatile*)(内存中的地址)中保留了
volatile
的可能副本
有意?这有关系吗?鉴于
word
是易失性的
@user2162550,如果
内存中的地址是一个硬件寄存器,那么是的,这很重要。但是寄存器本身也应该是易失性的,希望如此。然后就没关系了。虽然转换非常可疑。可能是Did的重复您将
volatile
*(uint32\u t volatile*)(内存中的地址)中移出
故意?这有关系吗?考虑到
word
是易失性的
@user2162550,如果
内存中的地址是一个硬件寄存器,那么它是有关系的。但是寄存器本身也应该是易失性的,希望如此。然后这就没关系了。不过,转换非常可疑。“缓存内存处理由CPU处理,而不是由编译器处理”通常不是正确的。有些编译器参与管理缓存,包括具有自动矢量化的编译器,这些编译器执行条带挖掘。@EricPostChil:它们可能会围绕缓存行为的假设进行优化,或发出指令来影响缓存行为(如预取)但它们不控制缓存逻辑。@R..:有些编译器会发出缓存命令,如将数据从缓存存储到内存或使缓存线无效的指令(这会强制该行的下一次加载来自内存)。这些都是与算术指令一样明确的动作,而不仅仅是提示或请求。说这样的编译器不控制缓存,与说这样的编译器不控制算术一样,没有任何意义,因为它只发出指令来影响处理器做算术。“缓存内存处理由CPU处理,而不是由编译器处理”通常不是正确的。有些编译器参与管理缓存,包括具有自动矢量化的编译器,这些编译器执行条带挖掘。@EricPostChil:它们可能会围绕缓存行为的假设进行优化,或发出指令来影响缓存行为(如预取)但它们不控制缓存逻辑。@R..:有些编译器会发出缓存命令,如将数据从缓存存储到内存或使其无效的指令