me icon indicating copy to clipboard operation
me copied to clipboard

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

Open nonocast opened this issue 2 years ago • 0 comments

今天在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++,竟然还有这么好的事情。。。

历史回顾

  • 1967年,Martin Richards为写操作系统和编译器开发了BCPL 随后,Ken Thompson改进BCPL,形成了B,取B是因为ALGOL 60中的字母A
  • 1970年,Ken在贝尔实验室(如果你对贝尔实验室没有概念的话,可以看一下浪潮之巅,就知道当时有多牛X)用B在DEC PDP-7写了第一个UNIX
  • 1973年,Dennis Ritchie为了将UNIX从PDP-7移植到PDP-11上,在B的基础上形成C,并用C重写了UNIX,至此形成C的原型
  • 1978年,Dennis Ritchie和Brian Kernighan合写了K&R C
  • 1989年,为了解决不兼容问题,ANSI对C进行了标准化,此标准称为C89
  • 1999年,针对C89进行了一些更新,此版本称为C99
  • 2011年12月8日,ISO正式发布了新的C语言的新标准C11,之前被称为C1X,官方名称为ISO/IEC 9899:2011

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

  • Classic C (K&R C)
  • C89 (C90) ANSI C (ANSI: 美国国家标准化协会)
  • C99: 引入许多特性,包括内联函数、可变数组、指定成员的初始化器等等,但编译器到目前为止并未100%实现,gcc, clang支持达90%以上,微软的C编译器最能支持到70%左右
  • C11: 引入字节对齐,范型机制(generic selection),多线程,静态断言,unicode。

参考: 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应该是一回事,两个写法。

扩展阅读

nonocast avatar May 25 '22 01:05 nonocast