今天下了Apple最新的XCode4.6,里面包含了最新的Apple LLVM4.2编译器,其中令人十分欣喜的是C语言编译器语言选项中多了C11以及gnu11。
之前在Apple LLVM4.0开始就已经支持了C11标准中一个比较重要的语法特性——泛型机制(详细可参考这篇博文:
C11标准的泛型机制
)。而现在,既然已经彻底推出了GNU11规范,那么我们来简单地探究一下,此次Apple LLVM4.2支持了哪些C11标准中的语法特性。
我这里列出了5大语法特性:
1、数据对齐(Alignment)
2、泛型表达式(Type-generic expressions)
3、原子数据类型(Atomics)
4、静态断言:(static assertion)
5、匿名结构与联合(Anonymous structures and unions)——其实这个语法特性在GNU扩展语法中已经被GCC编译器所支持。
下面提供一些样例代码来介绍这些特性以及如何使用这些特性:
//
// main.c
// CTest
//
// Created by zenny_chen on 12-12-1.
// Copyright (c) 2012年 zenny_chen. All rights reserved.
//
#include <stdio.h>
#include <stdalign.h>
#include <stddef.h> // no max_align_t
#include <string.h>
//#include <threads.h> not defined
//#include <uchar.h> not defined
//#include <stdatomic.h> not defined
#define Zenny_IsEqual4BasicTypes(a, b) _Generic((a), \
const char*: strcmp(a, b) == 0, \
char*: strcmp(a, b) == 0, \
const char[sizeof(a)]: strcmp(a, b) == 0, \
char[sizeof(a)]: strcmp(a, b) == 0, \
default: (a) == (b))
static volatile _Atomic(int) a = 100;
int main(int argc, const char * argv[])
{
// 1. Alignment
char _Alignas(long double) buf1[30] = { [0] = 10, [2] = -128, [29] = 127 };
char _Alignas(32) buf2[7] = { [0] = 10, [2] = -128 };
printf("The address of buf1 is: 0x%.16lX\n", (size_t)buf1); // 16-byte aligned
printf("The address of buf1 is: 0x%.16lX\n", (size_t)buf2); // 32-byte aligned
// 在C++的<cstddef>中定义了max_align_t为long double,但在C的<stddef.h>头文件中没有定义
printf("The max align size is: %lu\n", _Alignof(long double));
// 2. Type-generic expressions
printf("1 == 2? %d\n", Zenny_IsEqual4BasicTypes(1, 2));
const char words[] = "Hi";
printf("Hi == words? %d\n", Zenny_IsEqual4BasicTypes("Hi", words)); // Use char[3]
printf("words == Hi? %d\n", Zenny_IsEqual4BasicTypes(words, "Hi")); // Use const char[3]
// 3. Atomics
_Atomic(int) volatile *p = &a;
++(*p);
printf("The value is: %d\n", a);
// 4. _Static_assert: _Static_assert会在编译时做断言处理,因此第一个参数必须是常量表达式
_Static_assert(sizeof(void) == 1, "sizeof(void) !=1 and that is not expected!");
// 5. Anonymous structures and unions
struct T { int tag; union { int i; float f; }; };
struct T t = {.tag = 100, .f = -100.25f};
printf("The improper value is: %d\n", t.tag + t.i);
printf("The suitable value is: %f\n", t.tag + t.f);
return 0;
}
在Apple LLVM4.2中没被实现的C11标准有:
1、与
2、与
3、不支持_Noreturn函数指示符。
我同时也在Ubuntu下用了GCC4.7.2。该编译器支持了
而在最新的LLVM Clang中看到了Clang C编译器又增加了一个非常有趣的特性——函数重载。这个重载方式与限制跟C++中的一样。只需通过__attribute__((overloadable))来指定即可。下面看一下示例代码:
static void __attribute__((overloadable)) MyFunc(float x)
{
puts("This is a float function");
}
static int __attribute__((overloadable)) MyFunc(int x)
{
puts("This is an integer function");
return x;
}
int main(void)
{
MyFunc(1.0f);
MyFunc(1);
}
关于LLVM Clang更多信息可以参考此链接:http://clang.llvm.org/docs/index.html
这里会放最新LLVM Clang版本的手册以及各类文档。
而到了Apple LLVM 5.0之后,对C11标准的UTF-8、UTF-16以及UTF32编码格式都有了非常好的支持提升。C11标准中,字符串前缀u8表示以UTF-8编码的字符串,u前缀表示UTF-16编码的字符串,U前缀表示UTF-32编码的字符串。其中,UTF-8编码是变长编码格式,一个字符所占字节数从1到6字节不等。而UTF-16是定长编码,一个字符总是2个字节。UTF-32也是定长编码,一个字符总是4个字节。比如以下代码:
const char *utf8Str = u8"哈罗";
unichar utf16c = u'你';
unsigned utf32c = U'好';
const unichar *utf16Str = u",世界!";
printf("UTF-16 char size is: %lu\n", sizeof(u'你')); // 2个字节
printf("UTF-32 char size is: %lu\n", sizeof(U'好')); // 4个字节
NSString *str = [NSString stringWithCString:utf8Str encoding:NSUTF8StringEncoding];
NSLog(@"str = %@", str);
str = [NSString stringWithFormat:@"%C%C%S", utf16c, (unichar)utf32c, utf16Str];
NSLog(@"str = %@", str);
这里需要注意,u8前缀只能跟字符串字面量,而不能跟字符字面量。而u以及U既可以跟字符字面量也可以跟字符串字面量。
不过,在Apple LLVM5.0以及Apple LLVM 5.1中,尚未引入
原文链接: https://www.cnblogs.com/zenny-chen/archive/2013/01/30/2882923.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/77240
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!