我有一小段关于sizeof三元运算符的运算符的代码:
#include <stdio.h>
#include <stdbool.h>
int main()
{
bool a = true;
printf("%zu\n", sizeof(bool)); // Ok
printf("%zu\n", sizeof(a)); // Ok
printf("%zu\n", sizeof(a ? true : false)); // Why 4?
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出(GCC):
1
1
4 // Why 4?
Run Code Online (Sandbox Code Playgroud)
但在这里,
printf("%zu\n", sizeof(a ? true : false)); // Why 4?
Run Code Online (Sandbox Code Playgroud)
三元运算符返回boolean类型,sizeof bool类型是1C中的字节.
那为什么要sizeof(a ? true : false)输出四个字节?
代码:
int main(void)
{
auto a=1;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当文件具有.c扩展名时,MS Visual Studio 2012编译器会编译无错误.我一直认为,当你使用.c扩展名时,编译应该是根据C语法,而不是C++.而且,据我所知,自C++ 11以来只允许在C++中使用auto类型,这意味着该类型是从初始化程序推导出来的.
这是否意味着我的编译器不坚持C,或者C语言中的代码实际上是否正确?
使用%p转换说明符打印空指针是不确定的行为?
#include <stdio.h>
int main(void) {
void *p = NULL;
printf("%p", p);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这个问题适用于C标准,而不适用于C实现.
我读了关于属性的这个问题noreturn,它用于不返回调用者的函数.
然后我用C做了一个程序.
#include <stdio.h>
#include <stdnoreturn.h>
noreturn void func()
{
printf("noreturn func\n");
}
int main()
{
func();
}
Run Code Online (Sandbox Code Playgroud)
并使用以下代码生成代码的汇编:
.LC0:
.string "func"
func:
pushq %rbp
movq %rsp, %rbp
movl $.LC0, %edi
call puts
nop
popq %rbp
ret // ==> Here function return value.
main:
pushq %rbp
movq %rsp, %rbp
movl $0, %eax
call func
Run Code Online (Sandbox Code Playgroud)
为什么函数func()在提供noreturn属性后返回?
新的C11标准提供了对多线程的支持.
我的问题有点多元化,但绝对是可以回答的.
我看过C11 n1570选秀.
它说:
支持多个执行线程,包括改进的内存排序模型,原子对象和线程局部存储(
<stdatomic.h>和<threads.h>)
什么是改进的内存排序模型?c99标准如何/有什么变化?
如果有人深入研究它们并尝试解释所涉及的语义,我将不胜感激.
据我了解,C11支持:
我希望我什么都不错过?
从现在开始,标准库本身提供(将提供)多线程所需的所有功能,将来不需要POSIX和这样的库(用于多线程支持)?
最后,哪些编译器为上述功能提供支持?当支持这些时,是否有关于时间表的参考?
我记得在C++ 11中有一个编译器支持和功能的链接,也许是这样的?
我听说C11添加了泛型.我已经google了一下,看了一些文章,了解到有一个新的关键字(_Generic)和所有.但我似乎无法把握住这一切.
它是类似C#中的泛型还是C++中的模板?任何人都可以简单解释一下C11的泛型定义,它的语法和一个简单的示例用法示例吗?
当我查看有关GCC 8的新闻时,我看到他们增加了对2017版C语言的支持(不是C++ 17,真的是C17).但我在互联网上找不到任何关于它的信息.
它是像C11这样的新ISO版本,还是GCC团队用于编译器中某些更正的代号?
Stack Overflow问题的一些答案获取浮点数的IEEE单精度位建议使用union类型双关的结构(例如:将a的位float转换为a uint32_t):
union {
float f;
uint32_t u;
} un;
un.f = your_float;
uint32_t target = un.u;
Run Code Online (Sandbox Code Playgroud)
但是,uint32_t根据C99标准(至少草案n1124),联盟成员的值似乎未指定,其中第6.2.6.1.7节规定:
当值存储在union类型的对象的成员中时,对象表示的字节与该成员不对应但与其他成员对应的字节采用未指定的值.
C11 n1570草案至少有一个脚注似乎暗示不再是这种情况(见6.5.2.3中的脚注95):
如果用于读取union对象的内容的成员与上次用于在对象中存储值的成员不同,则将值的对象表示的适当部分重新解释为新类型中的对象表示形式在6.2.6中描述(一个过程有时被称为''punning'').这可能是陷阱表示.
但是,第C.6.6.1.7节中的案文与C11草案中的C99草案相同.
这种行为在C99下实际上是未指定的吗?它是否在C11中指定?我意识到大多数编译器似乎都支持这一点,但是知道它是在标准中指定还是只是一个非常常见的扩展会很好.
代码示例:
struct name
{
int a, b;
};
int main()
{
&(((struct name *)NULL)->b);
}
Run Code Online (Sandbox Code Playgroud)
这是否会导致未定义的行为?我们可以辩论它是否"取消引用无效",但是C11没有定义术语"解除引用".
6.5.3.2/4明确指出*在空指针上使用会导致未定义的行为; 但它并没有说同样的->,也没有定义a -> b为(*a).b; 它为每个运营商分别定义.
->6.5.2.3/4中的语义说:
后缀表达式后跟 - >运算符和标识符指定结构或联合对象的成员.该值是第一个表达式指向的对象的指定成员的值,并且是左值.
但是,NULL并没有指向一个对象,所以第二句似乎没有说明.
相关的可能是6.5.3.2/1:
约束:
一元运算
&符的操作数应该是函数指示符,[]一元或一元运算*符的结果 ,或者是一个左值,它指定一个不是位字段的对象,并且不用寄存器存储类说明符声明.
但是我觉得粗体文本是有缺陷的并且应该读取可能指定对象的左值,按照6.3.2.1/1(左值的定义) - C99弄乱了左值的定义,所以C11必须重写它,也许这个部分错过了.
6.3.2.1/1确实说:
左值是一个表达式(对象类型不是void)可能指定一个对象; 如果左值在评估时未指定对象,则行为未定义
但&操作员确实评估了它的操作数.(它不访问存储的值,但这是不同的).
这种长期推理似乎表明代码会导致UB,但它相当脆弱,我不清楚标准的作者是什么意图.如果事实上他们打算做任何事情,而不是让我们讨论:)
已经有很多关于C11和C11线程的问题,但我没有看到一个明确的答案的任何地方:
是否有任何 C库实现了在GNU/Linux上可用的C11线程接口?例如,提供"可选" <threads.h>和线程支持库一样thrd_create(),从该C11标准近页.376.
理想情况下,我想找到一个普通的,开源的或免费的库,用于通用/通用/多架构(例如,GNU/Linux,x86_64或portable-ish).
一些更有用和相关的SO链接:
库的一些非启动选项:
glibc图书馆没有 ; 自2012年以来有一个开放的bug ; 有GSoC提案,但似乎不被接受 ;pthreadC11线程;我对POSIX线程(很多很好的选项),Windows,IDE和C++ 11 都不感兴趣(我知道GNU libstdc++ …