const我的嵌入式C程序中有一个变量.它0在程序代码中定义和初始化.它通过链接描述文件放在一个特殊的ROM区域.可以通过特殊编程程序更改特殊区域的内容,但在主程序执行期间不能更改.
问题是我是否必须将常数声明为volatile.如果它没有标记为volatile,编译器是否允许用它替换所有引用0?或者是否有义务在程序执行期间至少加载一次?
请参阅以下在C和C++中有效的代码:
extern int output;
extern int input;
extern int error_flag;
void func(void)
{
if (0 != error_flag)
{
output = -1;
}
else
{
output = input;
}
}
Run Code Online (Sandbox Code Playgroud)
是否允许编译器以与下面类似的方式编译上述代码?
extern int output;
extern int input;
extern int error_flag;
void func(void)
{
output = -1;
if (0 == error_flag)
{
output = input;
}
}
Run Code Online (Sandbox Code Playgroud)
换句话说,被编译器允许生成(从第一个片段)的代码,总是让-1到一个临时分配output,然后分配input值,以output根据error_flag状态?
如果output将被声明为volatile ,编译器是否会被允许这样做?
如果output声明为atomic_int(stdatomic.h),是否允许编译器执行此操作?
大卫施瓦茨评论后更新:
如果编译器可以自由地向变量添加额外的写入,则似乎无法从C代码中判断是否存在数据争用.怎么判断这个?
假设x是一个共享的线程间变量而func总是返回0,那么下面的代码是否包含C11和C++ 11的数据竞争?请假设x是用两个不同的线程写入的,除了下面的switch语句外,总是有一个正确的锁.
int x; // global variable
...
int y; // local variable
...
switch (func())
{
case 1:
{
x = 0;
y = 1;
break;
}
case 2:
{
x = 0;
y = 2;
break;
}
case 3:
default:
{
y = 3;
break;
}
}
Run Code Online (Sandbox Code Playgroud)
标准中有一个注释(C11和C++ 11),它排除了向代码引入数据争用的编译器转换.是否允许编译器转换代码如下所示?下面的代码肯定包含一个数据竞争,但问题是编译器是否已经引入它或者它是否已经在原始代码中.虽然无法访问,但是对共享变量进行了不受保护的访问.
int x; // global variable
...
int y; // local variable
...
temp = x;
x = 0;
switch (func())
{
case 1:
{
y = 1;
break;
} …Run Code Online (Sandbox Code Playgroud) C11和C++ 11根据执行线程定义原子.而在托管环境中,很清楚线程是什么,在独立式语言实现中它是一个模糊的术语.
当系统调用或中断出现时,linux内核如何在用户模式和内核模式堆栈之间切换?我的意思是确切的机制是什么 - 用户模式堆栈指针会发生什么以及内核模式堆栈指针来自哪里?什么由硬件完成,什么必须由软件完成?
C 和 C++ 标准都指定了以下内容:
\n\n\n16.3.1 参数替换 (C++11)
\n6.10.3.1 参数替换 (C11)
\n在识别出调用类似函数的宏的参数后,将进行参数替换。替换列表中的参数,除非前面有 # 或 ## 预处理标记或后面有 ## 预处理标记(见下文),否则在其中包含的所有宏都已展开后将被相应的参数替换。在被替换之前,每个参数\xe2\x80\x99s预处理标记被完全宏替换,就好像它们形成了预处理文件的其余部分一样;没有其他可用的预处理标记。
\n
人们可以将本段解释为标准要求:
\n(1) 首先识别宏参数(以逗号分隔),然后分别展开每个参数中包含的所有宏,
\n或者
\n(2) 展开参数列表中包含的所有宏,然后识别每个参数。
\n为了说明这一点,让我们考虑以下示例代码:
\n#define CONDITION (0)\n\n#if (CONDITION > 0)\n#define FunctionAlias(par_a, par_b, par_opt, par_c) \\\n FunctionName(par_a, par_b, par_opt, par_c)\n#else\n#define FunctionAlias(par_a, par_b, par_c) \\\n FunctionName(par_a, par_b, par_c)\n#endif\n\nint global_a, global_b, global_c;\n#if (CONDITION > 0)\nint global_opt;\n#endif\n\nvoid FunctionName(int a, int b, int c)\n{\n}\n \nvoid AnotherFunction()\n{\n FunctionAlias(\n global_a,\n global_b,\n #if (CONDITION > 0)\n global_opt,\n …Run Code Online (Sandbox Code Playgroud) c ×6
c++ ×5
c++11 ×2
c11 ×2
concurrency ×1
embedded ×1
linux ×1
linux-kernel ×1
preprocessor ×1
standards ×1