%a和%A格式串?为什么%lx会将lx作为格式串, %fx只会将f作为格式串?C语言是如何区分开%f和%lf的?%ld和%d的区别?%d和%i的区别?%l %h和%d %o %u %x?万能格式串?

%a和%A格式串

C语言中,%a或%A用于在*printf函数中以十六进制浮点数的形式输出一个floatdouble类型的值。

输出格式一般是[-]0xh.hhhhp[+-]d,其中h.hhhh是十六进制的小数部分,p是分隔符,d是指数部分,底数是2.

        double value = 1.5;

        printf("%a\n", value);

        printf("%A\n", value);
输出结果:

        0x1.8p+0

        0X1.8P+0

为什么%lx会将lx作为格式串, %fx只会将f作为格式串?

libc解析格式串是按预定义的格式,当看到%l的时候,会向后查看是否是d/x/i/f等字符,但看到%g的时候就知道后面不管是任何格式都不是支持的,就会当做浮点数解析,当然后面的x当做原字符输出。

C语言是如何区分开%f和%lf的?

区分开它们是实现在libc. 具体到scanf函数执行时,libc会检查格式串是否包含%符号,如果有,继续从已知的格式串中枚举,发现单个f,就把输入当成float类型大小(一般为4字节),发现是lf组合,就把输入当成double类型大小(一般8字节)。需要注意,libc是将输入的数值写入到4字节或8字节的参数地址里面。有时,需要注意传入参数的大小,避免这种行为造成越界。

但在printf输出时,libc又会将%f和%lf统一用double类型输出,前提是编译器默认先把float类型参数先转换成double, 达成统一输出的目的。

%ld和%d的区别

%d默认是int格式,%ld的l代表long, 表示long int格式。如果int和long长度不同,二者有天差地别,因为libc会抓取的字节长度不同,最终数值也不同。类似的,%li, %lx, %lf同样也比base类型多了long,字节长度也可能有差异。

%d和%i的区别

  • 用于printf格式串: 没有区别。
  • 用于scanf格式串:
    %d只用于十进制整数,%i 除此之外,还可以匹配八进制、十六进制表示的整数。
    即:012用%d解析为12, %i解析是10.

%l %h和%d %o %u %x

C语言%d对应整形,%hd和%ld对应短整形和长整形,%lld代表long long int,%o代表八进制输出,%u是%d的无符号版本,格式串解析是在libc完成。

  • 不能有独立的%h或%l格式串,会和上面的组合格式产生冲突。
    • VS2019编译C代码只有%h格式符: 编译警告: 格式字符串“%h”未终止
  • %d/%o/%u/%x和%h或%l可以组合,比如%ho, %hu, %lo, %lx, %ld等。
  • 不能用大写模式,比如%L或者%LL, libc不识别

%h数值可能不是预期

在C语言中,假设short是2字节,%hd只会获取2个字节数据。如下第二句输出结果会变成-32768.

  • printf("%hd\n", 200);
  • printf("%hd\n", 32768);

无符号版本

  • 注意,%o和%x输出格式是无符号版本。

万能格式串

C语言提供了大量的格式串,记错了很可能导致编译错误或者运行异常。作为喜欢"偷懒"的程序员:

  • C语言没有那么灵活,格式串需要严格遵循变量类型(一些隐式转换的除外)。
  • ObjC基本类型格式串follow C语言,为对象类型引入了%@格式串,只要类实现了description()函数返回字符串。
  • C++ iostream定义了基本类型默认输出形式,cout不需要特别指定格式(除非指定特定格式)。
  • 更高级的编程语言,如Java/C#/Python/JS就更不在话下,格式串只是可选的行为。
  • Go也提供多种格式串,但也提供%v格式可以按默认格式输出基本类型和结构体。
    %v: 代表数值value.
  • PHP 提供了内置函数var_dump函数可以方便输出变量基本信息,不需要特别使用格式串。
  • Rust 提供 {:#?} 输出任何非基本类型的类JSON值。
  • Python 类实现 __str__ 方法可作为对象默认输出对应的字符串。

哪些编程语言支持字符串插值?

字符串插值并不是什么特别的技术,如果编程语言允许,字符串插值的引入并非难事。早期的一些编程语言,也许不认为这没有足够大的魅力让编程语言支援此功能,当然也有兼容代码的考量。某些编程语言又把字符串插值称为模板表达式。

  • C/ObjC/C++都没有字符串插值,可以用格式串%模拟插值。C++20引入的format方法让格式串更简约,可以不需要格式串类型,用{}或{}即可。
  • C# 6.0引入了字符串插值,本质是编译器将字符串中的大括号当成表达式,编译器可以解析求值并插入字符串中。
  • Python 3.6也引入了f-string字符串。
  • Swift也有字符串插值,格式稍微有些不同:print("hello, \(name)")
  • Rust没有字符串插值,和C++20 format方法的格式串有点像,用{}占位符。
  • Java没有字符串插值,只能+模拟字符串拼接。Java 15引入formatted方法,依然比较笨重:
    "hello, %s".formatted(name)
  • Go也不支持字符串插值,利用形如C语言%格式串%s或者用"+"实现字符串拼接。
  • JS ECMAScript 2015 (ES6) 开始支持字符串插值,不过它的叫法是模板字面量,不是普通用单引号或双引号标识的字符串,而是用反引号:
    let name = "JS";
    console.log(`Hello, ${name}!`); // Hello, JS!
    如果是单引号,console.log(‘Hello, ${name}!‘); // Hello, ${name}!
  • VB.NET之前的VB不支持字符串插值,允许&做字符串拼接。VB 14属于VB.NET,开始支持字符串插值,可参考:内插字符串 - Visual Basic | Microsoft Learn
    Console.WriteLine($"Hello, {name}!")
  • 仓颉 支持用 ${expression} 做字符串插值。注意,基本变量或表达式都可以,表达式可以包含多个声明表达式,以分号作为分隔符,最后一个是此插值的值。
    例如:str = "the str is: ${let a = 1; a + 1}" 此字符串最终为the str is: 2
  • Kotlin 支持${变量/函数/表达式}做字符串插值,对于单独变量,也可以省略大括号。
    • 如果变量没有大括号作为字符串插值,例如$a1,在同时定义变量a和a1时,会默认指代变量a1.

字符串插值和其他技术组合

  • C#允许字符串插值$和逐字字符串@同时使用,C# 8.0之前要求必须$在前面,@在后面,C# 8.0之后两种都允许。
  • Kotlin 允许原生字符串中用插值字符串。这造就了,原生字符串用如下三种形式都是表示单独的字符 $:
    • $ ${"$"} ${'$'}

字符串插值的本质

  • C# 字符串插值本质是一个语法糖,插值的变量被组装成object数组,利用string.Format()方法输出。

字符串插值的组合

  • C# 也支持多个带插值字符串拼接,比如$"hello {a}" + $"world, {b}".

数据输出形式

尽管大部分数据都会以人类最自然的形态展示,但总有一些例外。

  • 整型、字符、字符串按照数据原始值展示,注意转义字符有特定展示形态。
    例如:10, a, hello
  • 浮点数有精确度问题,根据默认有效数字展示
    不论单精度还是双精度浮点数类型,大部分编程语言默认只保留6位小数点,不论是C语言的float/double,或者仓颉的Float32或Float64. 即:
    1234567.0f用%f格式输出得到1234567.000000,0.234567890123用%f格式输出得到0.234568.
    • C/ObjC/C++/仓颉 均遵循如上规则。
    • 如果需要双精度浮点数更多有效数字,如果支持如下带小数点精度的格式,假如语言支持格式串,可用如下显式指示:如%.15f
    • Java/C# 默认输出更简洁,多余的0不会输出
      例如1234567.0f输出1234567.0, double类型1234567.1默认输出1234567.1
  • 布尔类型
    • C语言C99之前其实没有标准的布尔类型,都是用宏或者typedef整型或者char类型代替,输出形式其实就是整数0或者1.
    • 仓颉 Bool类型展现形式是true或者false.


若文章对您有帮助,欢迎关注 程序员小迷 。助您在编程路上越走越好!

微风不燥,阳光正好,你就像风一样经过这里,愿你停留的片刻温暖舒心。

我是 程序员小迷 (致力于C、C++、C#、Android、iOS、Java、Kotlin、Objective-C、Swift、Shell、JavaScript、TypeScript、Python等编程技术的技巧经验分享),若作品对您有帮助,请关注、分享、点赞、收藏、在看、喜欢,您的支持是我们为您提供帮助的最大动力。

你可能感兴趣的:(小话c语言,Java,小话c++,格式串,c,c++,objective-c,gc,java,swift)