前言:
此时朋友们对“十六进制打印会显示负数吗”大体比较看重,大家都想要分析一些“十六进制打印会显示负数吗”的相关内容。那么小编也在网摘上搜集了一些有关“十六进制打印会显示负数吗””的相关资讯,希望姐妹们能喜欢,兄弟们快快来学习一下吧!printf函数应该是每个人学习C语言遇到的第一个函数,很简单,却又很复杂(因为它可以对所有的C基础数据类型进行打印),估计很多人到现在只用过printf函数极少的功能。本文对printf函数的用法做了简要总结,包括C99的相关内容。 在C语言中,printf()、fprintf()、sprintf()函数都向输出流中写入可变数量的数据项,并且利用格式串来控制输出的形式。注意,这几个函数除了写入的目的位置不同以外,其他都是相同的。printf()函数写入stdout,fprintf()函数写入写入第一个参数FILE *stream中,sprintf()写入字符串中,这里仅介绍printf()函数。
int printf ( const char * format, ... );int fprintf(FILE *stream, const char *format, ...);int sprintf ( char * str, const char * format, ... );
printf函数按照格式化串(format)的格式将入参中的其他可变参数打印到stdout。格式化串包含普通字符和转换说明符,其中转换说明符以%开头,如下所示,最多包含5部分,[]中括号中的内容都是可选的。
%[flags][width][.precision][length]specifier
下图是对转换说明符构成的一个概括的介绍,接下来先从最后一部分转换说明符specifier开始介绍
1.转换说明符specifier
最后一部分的转换说明符是最重要的部分,也是必须指定的部分,其他前面4部分都是可选的。
d、i,有符号的10进制整数;u、o、x、X,都是无符号的,分别对应10进制,8进制,16进制小写,16进制大写;f、F,浮点数,对于浮点数,其精度默认是小数点后6位。其中F是C99之后添加的;
对于实数,f和F是没有区别的,主要用来打印infinity(无穷,包括正负无穷)和NaN(not a number,非数字)进行区分。下面的例子,说明了C99中INF,NAN等的产生和打印。
#include <stdio.h>#include <math.h>int main(){ printf("%f and %f\n", INFINITY, nan("0")); //输出: inf and nan printf("%F and %F\n", INFINITY, nan("0")); //输出: INF and NAN printf("1.0/0.0 = %F \n",1.0/0.0 ); //输出: 1.0/0.0 = INF printf("-1.0/0.0 = %F \n",-1.0/0.0 ); //输出: -1.0/0.0 = -INF printf("0.0/0.0 = %F \n",0.0/0.0 ); //输出: 0.0/0.0 = NAN return 0;}e和E,以科学计数法的形式表示double,两者的区别主要是打印中是大写E还是小写e,此外打印INFINITY和nan("0")时,e打印inf,而E打印INF;g,它根据数字的大小选择使用固定点格式(%f)或科学计数法格式(%e),目标是尽可能地以简洁的方式显示数字。 其工作的具体原理如下,确定精度 (precision):如果在 %g 格式说明符中指定了精度值,则使用该值。否则,默认精度为 6。精度为 0 时,等同于精度为 1。计算科学计数法下的指数 (exponent):
假设使用 %e 格式说明符,计算出该浮点数的指数。
根据指数大小选择格式:如果指数 exp 满足 -4 <= exp < precision,则使用固定点格式 %f,并使用 precision - (exp + 1) 的精度。否则,使用科学计数法格式 %e,并使用 precision - 1 的精度。去除尾随零和小数点: 除非使用 # 标志,否则会从结果的小数部分中移除尾随零,并且如果小数部分没有剩余的数字,则会移除小数点。
需要注意的是,%g 的输出并不一定与 %f 或 %e 中较短的输出完全一致。它基于指数大小来选择格式,而不是单纯地比较长度。
#include <stdio.h>int main() {double num1 = 123456.0;double num2 = 1234567.0;printf("num1: %g\n", num1); // 输出: 123456,去除尾随零和小数点printf("num2: %g\n", num2); // 输出: 1.23457e+06return 0;}G,和g的策略相同,只不过会在E和F之间选择(大写)。a和A,对应十六进制的浮点数(A为大写),是C99之后添加的,用于以十六进制格式输出浮点数。它可以让你更精确地查看浮点数的内部表示方式。具体的表示分4部分,符号: '+' 表示正数,'-' 表示负数。十六进制前缀: 0x。尾数: 一个十六进制数,以小数点 (.) 分隔整数部分和分数部分。指数: 指数以 p 表示,后面跟着一个十进制数,表示 2 的幂次方。
下面的例子,展示了a和A的表示方法,double和float都适用。
#include <stdio.h>int main() { double num = 3.14159; printf("num in hexadecimal: %a\n", num); // 输出: num in hexadecimal: 0x1.921f9f01b866ep+1 printf("num in hexadecimal: %A\n", num); // 输出: num in hexadecimal: 0X1.921F9F01B866EP+1 double big_num = 666.666666; printf("big_num in hexadecimal: %a\n", big_num); //输出:big_num in hexadecimal: 0x1.4d55554fbdad7p+9 float num_f = 3.14159; printf("num_f in hexadecimal: %a\n", num_f);//输出: num_f in hexadecimal: 0x1.921fap+1 double num_neg = -3.14159; printf("num_neg in hexadecimal: %a\n", num_neg);//输出: num_neg in hexadecimal: -0x1.921f9f01b866ep+1 double result = (1 + 0.5625 + 0.0078125 + 0.000244140625 + 0.0002288818359375 + 0.00000858306884765625 + 0.000000894069671630859375 + 0.0000000037252902984619140625 + 0.00000000256113708019256591796875 + 0.000000000116415321826934814453125 + 0.00000000000545597076416015625 + 0.00000000000034050690937042236328125 + 0.000000000000024868919445037841796875); printf("result= %f, num= %f",result, result * 2);//输出: result= 1.570795, num= 3.141590 return 0;}
那么0x1.921f9f01b866ep+1是如何表示3.14159的呢?其计算方法如下,小数点后的16的负次幂,小数点前的为16的正次幂,
上述计算的结果为1.570795,需要再乘以指数部分1.570795*2^(1)=3.141590。
c,将无符号整数打印为字符;
printf ("Characters: %c %c \n", 'a', 65);//输出: Characters: a As,字符串。如果指定了精度值(此时表示最大字节数),当达到精度值或者空字符时,停止写操作。p,把void *类型的指针转换成可打印的形式;
#include <stdio.h>int main() { int number = 42; int *ptr = &number; // Store the memory address of 'number' in 'ptr' printf("Value of 'number': %d\n", number); printf("Memory address of 'number': %p\n", (void*)ptr); return 0;}
输出为,从输出可以看出64位的系统指针的长度为8字节。
Value of 'number': 42Memory address of 'number': 0000007c9fbffcb4n,对应的实参必须是指向int类型的对象的指针,不会产生输出,而是将printf已经输出的字符的数量存储在对应的int类型对象的指针中。
#include <stdio.h>int main() { int count; printf("Hello,world! %n", &count); printf("count = %d\n", count); //输出:Hello,world! count = 13 return 0;}
上述例子将字符串 "Hello, world! " 输出到控制台,并将已写入的字符数量 (13 个字符,包括空格符) 存储到 count 变量中。
%,%号后面再加一个%,会在stdout中输出%。2.printf中的标志flags(可选)-,表示打印时左对齐,默认右对齐;+,有符号的数字总是以+或者-开头,默认是正数不打印+号,负数才会打印-号。空格,有符号的数字,如果是正数,在正数前面加空格。(+标志优先于空格标志)#,和转换说明符specifier为o、x、X一起使用时,打印的数字是以0、0x、0X开头,打印结果一看就知道是八进制数和十六进制数;和转换说明符specifier为a,A,e,E,f,F,g,G一起使用时,用于在浮点数输出时始终显示小数点,即使小数部分为 0。
#include <stdio.h>int main() { printf("%o\n", 10); //输出:12 printf("%#o\n", 10);//输出:012 printf("%x\n", 10);//输出:a printf("%#x\n", 10);//输出:0xa printf("%g\n", 1.0);//输出:1 printf("%#g\n", 1.0);//输出:1.000000 return 0;}0,用前导0在数的字段宽度内进行填充。如果转换说明符specifier为d、i、o、u、x、X,而且指定了精度,那么可以忽略标志0。3.printf的最小字段宽度(可选)
如果打印的数据位数太少,无法达到这个宽度,那么printf()会进行填充(默认会在数据项的左侧添加空格,从而使其在栏内右对齐)。如果数据的位数太多,超过了这个宽度,则不会裁剪,也会正常的完整显示数据。最小字段宽度可以设置为一个整数,也可以用*号表示,*号的的意思是从printf()函数的入参去指定输出字段的宽度,而不是在格式化字符串中指定。
#include <stdio.h>int main() { int width = 10; char string[] = "Hello"; printf("%*s\n", width, string); // 输出: " Hello" return 0;}4.printf的精度(可选).precision,这里假设定义了精度,同时其值设置为number。搭配整数相关的转换说明符,d, i, o, u, x, X,那么精度表示最小位数(如果数据不够,则添加前导0)。如果实际的数据长于number,也不会截断,会正常完整显示。注意这里如果number为0,同时printf要打印的数据为0,此时表示不打印0。
#include <stdio.h>int main() { printf("%.10d \n",10);//输出:0000000010 printf("%.0d\n", 0); // 不输出 return 0;}搭配a、 A、e、E、f 、F转换说明符,number指定了小数点后要打印的位数(默认为6位);搭配g和G转换说明符,number表示有效数字的个数;搭配s转换说明符,number表示打印的字符串的最大字节数;
#include <stdio.h>int main() { printf("%.2s \n","hello");//输出:he return 0;}如果number不是具体的数字,而是*号,表示从printf()函数的入参去指定number的具体值,而不是在格式化字符串中指定。5.printf的长度修饰符(可选)
长度修饰符搭配转换说明符,共同指定传入的实际参数的类型。
第一行为未指定长度修饰符时,转换说明符对应的默认的数据类型;hh、ll、j、z、t都是C99之后添加的。有了z和t后,对size_t和ptrdiff_t类型值的输出更方便了。
#include <stdio.h>int main() { size_t value = 1024; printf("The value is: %zu\n", value);// 输出:The value is: 1024 return 0;}
标签: #十六进制打印会显示负数吗