以下方法是否尊重“限制”合同?
void fun(int* restrict foo) {
int* bar = foo + 32;
for (int i = 0; i < 32; ++i)
*bar = 0;
}
Run Code Online (Sandbox Code Playgroud)
我的猜测是否定的,但我需要澄清一下。
长话短说——我使用 Ted Krovetz 的实现来计算UMAC和UMAC AE加密 ( http://www.fastcrypto.org/ )。
当我用 编译我的代码(和/或中的测试umac.c)时-std=c99,计算出的结果UMAC与预期完全不同(并且是错误的)。当我删除这个选项时,一切都像魅力一样。
有什么想法可能导致这种情况吗?我可以做什么来检查发生了什么以及什么产生了不同的结果?
$ gcc --version
gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
$ uname -a
xxx 3.13.0-43-generic #72-Ubuntu SMP .. x86_64 x86_64 x86_64 GNU/Linux
Run Code Online (Sandbox Code Playgroud)
我不使用任何其他选项 - 只是使用和不使用-std=c99.
再说几句话:
我会尝试联系 Ted Krovetz 并向他询问这个问题(可能是一些错误或其他问题),但这不是重点。这个问题有点笼统,这个具体问题可以看作是一个例子。
我跑了valgrind——没什么特别的。添加-Wall并且-Wextra-什么也没有了。听起来像UB,但valgrind没有抱怨任何事情。
这种情况非常有趣,花了我很多天和头痛才明白,问题不在我的代码中(我使用这个实现来实现复杂的协议),而是在算法中,尤其是在这个选项中。所以我决定征求意见。
在 C 和 C++ 中都有效的代码在用每种语言编译时会产生不同的行为吗?根本不相关,因为我们在这里谈论的是同一种语言。
这种没有“-std=c99”的巨大 fprintf 速度差异很接近,但还不够。
编辑
这是我的测试结果和我所做的(源/标题刚刚下载,我没有更改任何内容): …
所以这在C99:
label:
int ret = function(of, stuff);
Run Code Online (Sandbox Code Playgroud)
给出了一个编译时错误,而这个:
label:
;
int ret = function(of, stuff);
Run Code Online (Sandbox Code Playgroud)
工作得很好.
这是编译器错误吗?或者这是C标准定义中的错误?或者,如果这是C99标准的一部分,也许有人会捍卫C标准,声称这是完全合理的?
我在联合中声明了一个灵活的数组成员,如下所示:
#include <stdio.h>
union ut
{
int i;
int a[]; // flexible array member
};
int main(void)
{
union ut s;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
和编译器给出一个错误:
source_file.c:8:9: error: flexible array member in union
int a[];
Run Code Online (Sandbox Code Playgroud)
但是,声明的数组零大小如下:
union ut
{
int i;
int a[0]; // Zero length array
};
Run Code Online (Sandbox Code Playgroud)
它工作正常.
为什么零长度阵列工作精细?
在 C99 中初始化布尔数组的最佳方法是什么?
也许我可以用这个,我想。
bool f[5] = {false,};
Run Code Online (Sandbox Code Playgroud)
这真的好吗?
如果有更好的方法,请告诉我。
尝试嵌套宏调用,如下所示:
#include <stdint.h>
#define INT
#define LONG
#define AS(t) AS_##t
#define AS_INT as_int
#define AS_LONG as_long
#define LET(v, t) v. AS(t)
typedef union
{
int32_t as_int;
int64_t as_long;
} mytype_t;
int main()
{
mytype_t s;
s.AS(INT) = 10; /* This is OK */
LET(s, INT) = 10; /* This makes error */
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它产生错误:
main.c:xx:yy: error: ‘mytype_t {aka union <anonymous>}’ has no member named ‘AS_’
#define LET(v, t) v. AS(t)
^
main.c:zz:ww: note: in expansion of macro ‘LET’ …Run Code Online (Sandbox Code Playgroud) 我在我想声明一个数组的函数中的代码中的某个地方遇到了问题,但它失败了。经过一些调试后,我发现它在反汇编窗口中使用了 malloc,所以我增加了堆大小并且它工作正常!
所以我的问题是为什么 keil 使用堆作为局部变量?
这是变量声明代码:
uint8_t result[data->capacityBytes];
memset(result, 0, sizeof(result));
Run Code Online (Sandbox Code Playgroud)
我添加了标志 C99
本以为C不会再给我带来惊喜了,但这却让我大吃一惊。
const int NUM_FOO = 5;
....
int foo[NUM_FOO];
==>error C2057: expected constant expression
Run Code Online (Sandbox Code Playgroud)
我的 C++ 经验让我在内部#define尽可能地反对。所以这真是一个惊喜。VS2019,使用/TC编译。我认为 C99 无论如何都允许可变大小的数组。
任何人都可以解释为什么会发生拒绝,因为编译器在编译时肯定知道数组的大小?
C99不是允许可变大小数组吗?
我知道 C99 之前的编译器需要在函数开头声明变量来计算堆栈大小。然后要求就被取消了。如今,除了向后兼容性之外,仍然坚持该方案是否有任何好处,或者也许仅在需要变量时以及在更需要变量的地方才声明变量?(例如,在 if 语句中,其中一个分支需要变量,但第二个分支不需要)
鉴于以下代码,我有一些与类型双关相关的问题。我看不出这没有违反严格的别名规则,但我无法指出具体的违规行为。我最好的猜测是,将联合成员传递到函数中违反了严格的别名。
以下代码位于Compiler Explorer上。
#include <stdint.h>
union my_type
{
uint8_t m8[8];
uint16_t m16[4];
uint32_t m32[2];
uint64_t m64;
};
int func(uint16_t *x, uint32_t *y)
{
return *y += *x;
}
int main(int argc, char *argv[])
{
union my_type mine = {.m64 = 1234567890};
return func(mine.m16, mine.m32);
}
Run Code Online (Sandbox Code Playgroud)
我的观察:
func不互相别名,func则不违反严格别名。unionfor 类型双关。m16和m32进入func必须违反某些内容。我的问题:
func?