nonocast / me

记录和分享技术的博客
http://nonocast.cn
MIT License
20 stars 0 forks source link

学习 C/C++ (Part 18: struct) #286

Open nonocast opened 2 years ago

nonocast commented 2 years ago

今天在obs看到这样一句代码

struct encoder_packet packet = {.type = OBS_ENCODER_VIDEO, .timebase_den = 1, .keyframe = true};

查了一下这个叫做Designated Initializers,不限于struct,gcc的文档中描述: Standard C90中初始化必须按顺序执行,在ISO C99中扩展支持指定初始化。

Array

int a[6] = { [4] = 29, [2] = 15 }; 等同于 int a[6] = { 0, 0, 15, 0, 29, 0};

Struct

struct point { int x, y}

对应初始化

struct point p { .y = 1, .x = 3 };

等同于

struct point p { 3, 1 };

注: Designated Inits仅支持C,不支持C++,竟然还有这么好的事情。。。

历史回顾

从1973年算起,也差不多有40年了,其中主要的4个版本

参考: C89(C90)、C99、C11——C语言的三套标准

印象中,在C语言中局部变量的定义必须是在函数开头的,其实这是C89的规范,到了C99取消了这个限制,变量可以在任意位置定义。包括ANSI C不允许在for定义i,必须先int i再for,看来选对标准非常重要。

What is the default C -std standard version for the current GCC (especially on Ubuntu)? - Stack Overflow

c.c

#include <stdio.h>

int main(void) {
#ifdef __STDC_VERSION__
    printf("__STDC_VERSION__ = %ld \n", __STDC_VERSION__);
#endif
#ifdef __STRICT_ANSI__
    puts("__STRICT_ANSI__");
#endif
    return 0;
}

Test with (c.sh):

#!/usr/bin/env bash
for std in c89 c99 c11 c17 gnu89 gnu99 gnu11 gnu17; do
  echo $std
  gcc -std=$std -o c.out c.c
  ./c.out
  echo
done
echo default
gcc -o c.out c.c
./c.out

Outcome:

% ./c.sh
c89
__STRICT_ANSI__

c99
__STDC_VERSION__ = 199901 
__STRICT_ANSI__

c11
__STDC_VERSION__ = 201112 
__STRICT_ANSI__

c17
__STDC_VERSION__ = 201710 
__STRICT_ANSI__

gnu89

gnu99
__STDC_VERSION__ = 199901 

gnu11
__STDC_VERSION__ = 201112 

gnu17
__STDC_VERSION__ = 201710 

default
__STDC_VERSION__ = 201710 

可以看到gcc还是clang目前采用的已经是gun17。C17并未引入新的语言特性,只对C11进行了补充和修正。此外,C17和gun17应该是一回事,两个写法。

扩展阅读