标签: c99

获取非原型声明的编译警告

在 C 中,函数声明可以是原型声明或非原型声明。例如,考虑以下最小程序:

int foo (); /* non-prototype declaration */

int bar (void); /* prototype declaration */

int main (int argc, char **argv)
{
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

尽管在 C99 中非原型声明已经过时,但我无法让 GCC 抱怨它们。例如,使用 GCC 编译上述程序并启用所有错误就会成功:

$ gcc -std=c99 -pedantic -Werror -Wall test.c
$
Run Code Online (Sandbox Code Playgroud)

有没有办法说服 GCC 对不是原型的函数声明发出警告?

(问题的灵感来自Keith Thompson回答。)

c gcc compilation c99 compiler-warnings

3
推荐指数
1
解决办法
1205
查看次数

C99 预处理器中的 static_if

是否可以在 C99 中实现 static_if?

#define STATIC_IF(COND, ...) \
     if (COND) MACRO1(__VA_ARGS__); \
     else MACRO2(__VA_ARGS__);
Run Code Online (Sandbox Code Playgroud)

我如何STATIC_IF(…)在这里正确实施?根据COND参数,要么应该传递给MACRO1要么MACRO2,但两个宏的参数看起来不同。COND是静态可测试的,类似于sizeof (…) > 42.

  • #if COND然后#define STATIC_IF MACRO1……不适用于我的用例。
  • 我不能使用编译器特定的解决方案。

c c99 c-preprocessor static-if

3
推荐指数
1
解决办法
3287
查看次数

在 C99 中将运算符作为参数传递

我想在 C99 中将运算符作为参数传递。我的解决方案是这样的:

int add(int l, int r)
{
    return l + r;
}

int sub(int l, int r)
{
    return l - r;
}

// ... long list of operator functions

int perform(int (*f)(int, int), int left, int right)
{
    return f(left, right);
}

int main(void)
{
    int a = perform(&add, 3, 2);
}
Run Code Online (Sandbox Code Playgroud)

有没有其他方法可以做到?我不想为每个运算符编写一个函数。

它可能看起来像这样:

int a = perform(something_cool_here, 3, 2);

c operators c99 parameter-passing

3
推荐指数
1
解决办法
1364
查看次数

C99 标准中的哪里说有符号整数溢出是未定义的行为?

C99 标准中的哪里说有符号整数溢出是未定义的行为?

我在 6.2.5 节看到关于无符号整数溢出的评论是明确定义的(请参阅为什么无符号整数溢出定义了行为,但有符号整数溢出不是?):

涉及无符号操作数的计算永远不会溢出,因为无法由结果无符号整数类型表示的结果以比结果类型可以表示的最大值大 1 的数为模减少。

但我在附录 J 中查看未定义行为,我只在列表中看到这些类似的项目:

具有符号提升类型的表达式被左移,并且表达式的值为负或移位的结果将无法在提升类型中表示

无法表示整数算术或转换函数的结果值

(注意这是指“整数算术函数”,而不是整数算术本身

c c99 undefined-behavior

3
推荐指数
1
解决办法
580
查看次数

用于数组数组的指定初始化程序

我们可能知道c99中的指定初始值设定项以及它们用于初始化大型const数组的方式:

const int vals[] = {
    [0] = 10,
    [10] = 12
}
Run Code Online (Sandbox Code Playgroud)

其中initalizes指数0vals10和索引10vals12.

我的问题是如何将这种类型的指定初始化器用于数组数组.这是我的示例代码:

typedef enum {
    COMMON = 0,
    STRINGS,
    KEY,
    PRECUSSIVE,
    GUITAR,
    KEYBOARD,
    BASS,
    PIANO,
    DRUMS,
    _INST_MAX
} instrument_classification_t;
static const int * const instrument_class_hierarchy[] = {
    [COMMON] = {STRINGS, KEY, PRECUSSIVE, _INST_MAX},
    [STRINGS] = {GUITAR, BASS, _INST_MAX},
    [KEY] = {PIANO, KEYBOARD, _INST_MAX},
    [PRECUSSIVE] = {DRUMS, _INST_MAX},
    [GUITAR] = NULL,
    [KEYBOARD] = NULL, …
Run Code Online (Sandbox Code Playgroud)

c c99

3
推荐指数
1
解决办法
489
查看次数

在C文件中单独使用单个内联函数是否相关?

我看到这个例子,我有一个crc32.c文件,其中包含:

inline int32_t crc32_compute(int32_t *buffer, size_t size) {
   ...
}
Run Code Online (Sandbox Code Playgroud)

在头文件中我找到:

extern inline int32_t crc32_compute(int32_t *buffer, size_t size);
Run Code Online (Sandbox Code Playgroud)

对我来说,inline关键字没有任何效果,因为该函数应该在头文件上而不是在C文件上声明.这是正确的吗?

c inline c99

3
推荐指数
1
解决办法
80
查看次数

数组的外部声明

我有一个数组,其大小在源文件中定义的编译时确定。

const int array[] = {1, 3, 3, 7};
Run Code Online (Sandbox Code Playgroud)

元素的数量将来可能会发生变化,因此我宁愿不在括号中对其进行硬编码。

这个数组需要从几个源文件中访问,所以我试图在头文件中添加一个 extern 声明。但是,由于隐式数组大小,我不确定这是否可行。我尝试了两种变体:

extern const int array[]; // Warning: size of symbol `array' changed from 8 to 16
extern const int *array; // error: conflicting types for 'array'
Run Code Online (Sandbox Code Playgroud)

是否可以这样做,或者我应该寻找解决方法?

c99 extern variable-declaration

3
推荐指数
1
解决办法
3022
查看次数

C99和C++03中空指针定义的区别

N2431是介绍的论文nullptr。它说:

当前的 C++ 标准提供了一个特殊规则,即 0 既是整数常量又是空指针常量。来自 [C++03] 条款 4.10:

空指针常量是整数类型的整数常量表达式 (expr.const) 右值,其计算结果为零。空指针常量可以转换为指针类型;结果是该类型的空指针值,并且与指向对象的指针或指向函数类型的指针的所有其他值区分开来。相同类型的两个空指针值比较相等。将空指针常量转换为指向 cv 限定类型的指针是一次转换,而不是指针转换后跟限定转换 (conv.qual) 的序列。

此公式基于原始 K&R C 定义,与 C89 和 C99 中的定义不同。C 标准 [C99] 说(第 6.3.2.3 条):

值为 0 的整数常量表达式,或转换为 void * 类型的此类表达式,称为空指针常量。 [55] 如果将空指针常量转换为指针类型,则生成的指针(称为空指针)保证与指向任何对象或函数的指针不相等。

让我们忽略“[c++03] 公式是基于原始的 K&R C 定义”部分而关注“[c++03 公式] 与 [...] C99 中的定义不同”。

我不清楚 C++03 和 C99 定义在哪些方面有所不同。是的,它们在书面标准中有不同的正式定义(正如我们所看到的引用不同),但从实践的角度来看,这意味着什么?他们真的有区别吗?如果我正确阅读这篇文章,它的语气暗示存在差异。如果有,它们是什么?我无法理解/理解基于标准引用的差异。

我没有具体询问 C++03 或 C99 空指针是如何定义、表示和/或实现的。我的问题是关于 C++03 和 C99 空指针定义(可能还有它们的实现,如果为了回答这个问题而进行演示很重要)有何不同,答案可以包含 C++03 和C99 空指针,但仅作为说明差异或显示差异的帮助点。也就是说,仅提供定义或对每个定义的解释不被视为对这个问题的回答。

我完全知道这nullptr是在 C++11 及更高版本中表达空指针的首选方式。这不是问题。

c c++ c99 language-lawyer c++03

3
推荐指数
1
解决办法
139
查看次数

在开始时调用带有 va_list 参数的函数需要 va_start() 吗?

具有以下标头的函数:

int max(int n, va_list vals)
Run Code Online (Sandbox Code Playgroud)

在函数内部调用:

int max_first(int n, ...)
Run Code Online (Sandbox Code Playgroud)

需要va_start(vals, n)在身体开始时调用吗?我试过没有,它有效,但我不明白哪种是正确的做法。

int max(int n, va_list vals)
{
    va_start(vals, n);
    // etc
}
Run Code Online (Sandbox Code Playgroud)

c c99 variadic-functions

3
推荐指数
1
解决办法
219
查看次数

我应该如何获得浮点值的小数部分?

我有一个xtype变量float,我需要它的小数部分。我知道我可以得到它

  • x - floorf(x), 或者
  • fmodf(x, 1.0f)

我的问题:其中一个总是比另一个更可取吗?它们实际上是一样的吗?我可以考虑第三种选择吗?

笔记:

  • 如果答案取决于我正在使用的处理器,那就让它成为 x86_64,如果你能详细说明其他处理器,那会很好。
  • 请确保并参考 的负值行为x。我不介意这种行为或那种行为,但我需要知道这种行为是什么。

c floating-point c99 floor libm

3
推荐指数
1
解决办法
101
查看次数