【问题标题】:Curly braces as argument of function花括号作为函数的参数
【发布时间】:2017-05-31 11:52:31
【问题描述】:

我在一些源代码中注意到这一行:

if(pthread_create((pthread_t[]){}, 0, start_thread, pthread_args)) {
...

它工作正常,但如何理解第一个参数? 看来,花括号转换为pthread_t[] 类型。

附:我用谷歌搜索,但没有找到答案,只有一些猜测(某种形式的初始化,还是 c 的遗留特性?)

【问题讨论】:

  • 这是一个compound literal
  • @Someprogrammerdude 谢谢!就是这样,我想要。

标签: c


【解决方案1】:

这是一个compound literal,自initializer braces cannot be empty 以来违反了约束:

(pthread_t[]){}

使用gcc -std=c99 -Wall -Wextra -Wpedantic 会产生警告:

compound_literal_pthread.c:6:36: warning: ISO C forbids empty initializer braces [-Wpedantic]
     pthread_t *ptr = (pthread_t []){};

结果似乎是指向pthread_t 的指针,尽管我没有在 gcc 手册中看到这种行为。请注意,在 C++ 中,允许空括号作为初始值设定项,它们等价于 { 0 }。这种行为似乎支持 C,但 gcc 没有记录。我怀疑这就是这里发生的事情,使上面的表达式等同于:

(pthread_t[]){ 0 }

在我的系统上,pthread_tunsigned longtypedef,因此该表达式将创建一个仅包含0 元素的pthread_t 数组。该数组将衰减为函数调用中指向pthread_t 的指针。

【讨论】:

  • 并且作为一个变态的副作用,线程是不可加入的,因为代码没有保存pthread_t 可访问。实际上,线程是分离的,没有正式分离的好处。作为创建线程的一种方式,它还有很多不足之处。
  • 认为 C 中的每种类型都可以用{ 0 } 正确初始化,但我不清楚为什么不允许使用空括号:因为任何单个元素允许被初始化的对象是隐式的,为什么不一次将它们全部设为真呢? (并且{ 0 } 可能在技术上对许多类型都是允许的,但在干净易读的意义上不是“正确的”)
  • @Leushenko-- 副手 我想不出{ 0 } 不适用的类型,尽管可能会有关于缺少大括号的警告。 IAC,如果我理解正确的话,我认为您对缺少元素的初始化程序所说的话是有道理的。我相信有些人觉得这是 C++ 正确的 C 规范中的一个“错误”。顺便说一句,您观察到{ 0 } 对于特定类型可能不是“正确”的,这就是为什么我仔细检查pthread_tunsigned long
【解决方案2】:

这是@some-programmer-dude 提到的compound literal

在这种特定情况下,它用于创建一个数组来存储 thread_id 并在以后释放它,而无需创建额外的变量。这是必要的,因为pthread_create 不接受 NULL 作为thread_id 的参数。

【讨论】:

    【解决方案3】:

    您正在使用pthread[] 创建一个数组。如果为参数定义了长度,则可以在花括号中传递值。

    【讨论】:

      【解决方案4】:

      您正在处理的是一个数组初始值设定项,它恰好是空数组。你通常会发现它:

      int my_array[] = (int[]){10, 20, 30};
      

      它会初始化my_array 以包含三个元素。这里没有元素,因此语法很尴尬。

      【讨论】:

      • 一个空的大括号括起来的列表是否被认为是有效的语法? AFAIR,它必须至少包含一个元素。
      • 是的,这是一个有效的语法。在这种情况下,你不需要写花括号,但你可以。
      • @JohannesMols-- 这不是有效的语法,在初始化器中使用空括号是违反约束的。
      • int my_array[] = (int[]){10, 20, 30}; 给出error: array initialized from non-constant array expression。也许你的意思是int *my_array = (int[]){10, 20, 30};
      • 请注意,GCC(7.1.0 测试)允许复合文字作为初始值设定项,除非您打开 -pedantic 警告/错误。例如,使用gcc -O3 -g -std=c11 -Wall -Wextra -Werror -pedantic -c di59.c 会产生错误(如果没有-Werror 将是警告):di59.c:1:18: error: initializer element is not constant [-Werror=pedantic] int my_array[] = (int[]){10, 20, 30}; 但将-pedantic 排除在选项之外,它会得到一个干净的健康账单。复合文字的 'cast' 部分应作为基本初始化程序删除,当然:int my_array[] = { 10, 20, 30 };.
      猜你喜欢
      • 2016-10-09
      • 2019-09-20
      • 2011-05-08
      • 1970-01-01
      • 1970-01-01
      • 2016-10-06
      • 2016-05-28
      • 2020-11-13
      • 1970-01-01
      相关资源
      最近更新 更多