标签: c23

为什么关键字 false 在 gcc C23 中不是整数常量表达式?

gcc -std=c23最新的 gcc 13.x (trunk) 给出了此代码的编译器错误 ( ):

\n
int* p = false;\n
Run Code Online (Sandbox Code Playgroud)\n
\n

错误:int *使用类型“ ”初始化类型“ _Bool”时出现类型不兼容

\n
\n

这怎么可能是正确的呢?

\n
\n

C23 6.2.5 \xc2\xa78-9(类型 - 整数类型的定义):

\n
\n

bool与标准有符号整数类型相对应的类型和无符号整数类型是标准无符号整数类型

\n

标准有符号整数类型和标准无符号整数类型统称为标准整数类型

\n
\n

C23 6.6 \xc2\xa78 (常量表达式 - 整型常量表达式的定义):

\n
\n

整数常量表达式应具有整数类型...

\n
\n

C23 6.3.2.3(指针-空指针常量的定义)

\n
\n

值为 0 的整型常量表达式,此类表达式转换为 类型void *,或预定义常量nullptr称为空指针常量

\n
\n

C23 6.5.16.1(简单分配):

\n
\n

约束
\n/--/ …

c gcc null-pointer language-lawyer c23

31
推荐指数
2
解决办法
2505
查看次数

C23 中 int main() 和 int main(void) 等价原型吗?

C23 在函数声明符中引入了新的语义:

\n
\n

6.7.6.3 函数声明符

\n

[...]

\n

13\xc2\xa0\xc2\xa0\xc2\xa0对于没有参数类型列表的函数声明符:效果就像是使用由关键字 组成的参数类型列表进行声明void。函数声明符提供函数的原型。

\n
\n

这似乎意味着具有空参数列表的函数定义可以等效地用()or编写(void)

\n

然而,该函数似乎并不能保证这种main等价性:

\n
\n

5.1.2.2.1 程序启动

\n

程序启动时调用的函数名为main。该实现没有声明该函数的原型。它的返回类型应为int且不带参数定义:

\n
int main(void) { /* ... */ }\n
Run Code Online (Sandbox Code Playgroud)\n

或带有两个参数(此处称为argcargv,但可以使用任何名称,因为它们对于声明它们的函数来说是本地的):

\n
int main(int argc, char *argv[]) { /* ... */ }\n
Run Code Online (Sandbox Code Playgroud)\n

或等效的或以某种其他实现定义的方式。

\n
\n

这似乎并不能保证 是 的int main() { /* ... */ }有效定义main,或者等效定义是否涵盖此变体?

\n
\n …

c language-lawyer function-prototypes c23

18
推荐指数
1
解决办法
2789
查看次数

C23 自动与 C++11 自动

C23 标准显然引入了使用“auto”关键字进行自动类型推导,请参阅此处,就像 C++11 中一样。然而,似乎存在一些差异。

根据here,https://en.cppreference.com/w/cpp/keyword/auto,在C++11之后,不再auto是C++中的存储持续时间说明符。

然而,我无法轻易找到 C23 的等效声明。在C23中是否仍然auto是C中的存储类说明符?

还可以int auto x = 1;用C23写吗?

编辑:第一个问题的答案是肯定的。但正如 Andrew Henle 在下面的评论中指出的,第二个问题是不同的:

还可以float auto x = 1;用C23写吗?

正如 @AndrewHenle 和 @VladfromMoscow 在标准文档中引用的那样,6.7.1 存储类说明符,第 4 段

auto 仅应出现在具有文件范围的标识符的声明说明符中,或者如果要从初始值设定项推断类型,则应与其他存储类说明符一起出现。

float auto x = 1;如果此声明不在文件范围内,则这似乎不涵盖这种情况。

这句话的解释是什么?

还有一个问题:这句话看起来很混乱,因为我们肯定可以使用 auto 而无需“其他存储说明符”,不是吗?喜欢auto a = 1;

c declaration auto c23

11
推荐指数
1
解决办法
1453
查看次数

新 C23 #embed 指令的目的是什么?

即将推出的 C23 标准中提供了新的预处理器指令:#embed

这是一个简单的例子:

// Placing a small image resource.

#include <stddef.h>

void show_icon(const unsigned char *, size_t);

int main (int, char*[]) {
    static const unsigned char icon_data[] = {
#embed "black_sheep.ico"
    };
    show_icon(icon_data, sizeof(icon_data));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是一个更详细的方法,从二进制数据初始化非数组(无论这意味着什么):

int main() {
    /* Braces may be kept or elided as per normal initialization rules */
    int i = {
#embed "i.dat"
    }; /* i value is [0, 2^(embed element width)) first entry */
    int i2 =
#embed "i.dat"
    ; …
Run Code Online (Sandbox Code Playgroud)

c language-lawyer c23

10
推荐指数
1
解决办法
6129
查看次数

nullptr_t 是否会破坏类型双关或指针转换?

考虑这个联盟:

\n
typedef union\n{\n  void*      vptr;\n  nullptr_t  nptr;\n} pun_intended;\n
Run Code Online (Sandbox Code Playgroud)\n

nullptr_t据说与void* 1)兼容。好吧,如果我们将 初始化void*为某个非零值怎么办?

\n
pun_intended foo = { .vptr = (void*)42 }; \n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 根据 C23 6.3.2.3 \xc2\xa74,此转换被认为是合法的(impl.defined),或者至少在nullptr_t引入之前是合法的。
  • \n
  • 那么联合类型双关语又如何呢?据说也是合法的。
  • \n
  • 以及使用字符类型指针检查 C 中任何类型的内部表示,该指针在 C23, 6.3.2.3 \xc2\xa77 之前都是明确定义的。
  • \n
\n

完整示例:

\n
#include <stdio.h>\n#include <inttypes.h>\n#include <stddef.h>\n\ntypedef union\n{\n  void*      vptr;\n  nullptr_t  nptr;    \n} pun_intended;\n\nint main(void)\n{\n  pun_intended foo = { .vptr = (void*)42 };\n  printf("Value: %" PRIuPTR "\\n", (uintptr_t)foo.vptr);\n\n  if(foo.nptr != (void*)42)\n  {\n    puts("It …
Run Code Online (Sandbox Code Playgroud)

c nullptr language-lawyer type-punning c23

10
推荐指数
1
解决办法
259
查看次数

在 C23 之前如何对空指针使用“nullptr”?

在C23中,nullptr关键字得到了标准化。我也更愿意使用C23 之前nullptr的版本NULL,因为这意味着我可以编写可编译的代码:

  • C,C23之前
  • C,从 C23 开始
  • C++

我可以简单地NULL在两种语言和每个 C 标准中使用,但这在 C++ 代码中是非常不寻常的,并且nullptr无论如何正在成为两种语言的规范。

#define据我所知,语言中不允许使用替换关键字,这可能会在定义兼容性宏时引起问题。基本上,我需要:

// only if this is neither C++ nor C23
#define nullptr /* something */
Run Code Online (Sandbox Code Playgroud)

我怎样才能正确定义这个宏?

c c-preprocessor c23

9
推荐指数
2
解决办法
677
查看次数

C23 中的 [[reproducible]] 和 [[unsequenced]] 属性是什么?什么时候应该使用它们?

C23 引入了属性[[reproducible]][[unsequenced]]

  • 他们背后的动机是什么?
  • 它们是如何定义的,它们对函数有什么影响?
  • 我应该将它们应用于什么样的功能?

c attributes c23

8
推荐指数
1
解决办法
422
查看次数

为什么 gcc 13 不显示正确的二进制表示形式?

在这里回答问题时,我做了以下例子:

#include <stdio.h>
#include <math.h>

int main (void) 
{
  float_t a = -248.75;
  printf("%f\n", a);

  unsigned char* ptr = (unsigned char*)&a;
  for(size_t i=0; i<sizeof(a); i++)
  {
    printf("%.2X ", ptr[i]);
  }
}
Run Code Online (Sandbox Code Playgroud)

在版本 13 之前的 gcc 以及 clang 的所有版本上,这给出了预期的输出(x86 小端):

-248.750000
00 C0 78 C3 
Run Code Online (Sandbox Code Playgroud)

然而,当使用 gcc 13.1 编译时,我得到无意义的输出:

-248.750000
00 00 00 00 
Run Code Online (Sandbox Code Playgroud)

进一步检查发现,罪魁祸首就是这个选项-std=c2x。如果我删除它,程序将按预期运行。

使用的编译器选项:-std=c2x -pedantic-errors -Wall -Wextra -O3 -lm. https://godbolt.org/z/4qbo74eEW

这是 gcc 中的已知错误吗?

c gcc compiler-bug pointer-conversion c23

7
推荐指数
1
解决办法
177
查看次数

long_double_t 是否存在(标准 C: C23)

新标准C(ISO/IEC 9899:2023,又名C23),
在附录H中,定义了几个宏和类型,
相对于实数和复数算术,
并符合 ISO/IEC 60559 标准(浮点算术)。

根据 H.1 小节,存在三个
实现定义的宏来测试
与附件 H 定义的一致性。

__STDC_IEC_60559_TYPES__  
__STDC_IEC_60559_BFP__  
__STDC_IEC_60559_DFP__  
Run Code Online (Sandbox Code Playgroud)

此外,要“激活”关联的宏和类型,
用户必须定义​​宏:

__STDC_WANT_IEC_60559_TYPES_EXT__  
Run Code Online (Sandbox Code Playgroud)

该标准的措辞在几个细节上很明确:

  • 如果__STDC_IEC_60559_BFP__是由编译器定义的,则意味着_FloatN,_FloatN_t和其他_FloatN*类型也已定义。
  • 如果__STDC_IEC_60559_DFP__是由编译器定义的,则意味着_DecimalN,_DecimalN_t和其他_DecimalN*类型也已定义。
  • __STDC_IEC_60559_TYPES__无论哪种情况,都会定义宏。
  • 如果定义了宏,则意味着至少定义了__STDC_IEC_60559_TYPES__一个宏__STDC_IEC_60559_BFP__或(或两者)。__STDC_IEC_60559_DFP__

在 H.11 小节中,类型long_double_t被添加到 中<math.h>

long_double_t但是,我无法推断在哪些条件下可以确保给定实现中的存在。

问题:

如果__STDC_IEC_60559_TYPES__已定义,是否足以确定long_double_t也在 中定义<math.h>

我的怀疑来自以下可能出现的特殊情况:

  • __STDC_IEC_60559_TYPES____STDC_IEC_60559_DFP__已定义,但__STDC_IEC_60559_BFP__未定义。

在本例中,定义了十进制类型。
但是,long_double_t不是十进制类型。

子问题:
宏是否 …

c language-lawyer c23

7
推荐指数
1
解决办法
121
查看次数

为什么 C23 标准减少了实现必须支持的对象的最大大小?

我目前正在阅读 C23 标准的新草案(N3088),并且我注意到在 \xc2\xa75.2.4.1 中该标准指出:

\n
\n

该实现应能够翻译和执行使用但不超过\n这些结构和实体的以下限制的程序:...对象中的 32767 字节(仅在托管环境中)

\n
\n

这是 ANSI C/C89 中的数字,自 C99 起它被提高到 65535 - 为何将其降低回原来的数量?

\n

我试图在此处和WG 14 文档日志中查找任何对此的引用,但没有找到任何内容。

\n

c standards c23

6
推荐指数
1
解决办法
243
查看次数