C语言基础之格式化占位符

在 printf 系列函数中,下列哪个格式化占位符有可能导致内存任意写风险 [A]

A. %n
B. %d
C. %p
D. %s

使用printf修改变量的值 —— VS2008中使用%n输出遇到的问题及解决方法

#include <stdio.h>

int main(void)
{
    int e;
    int i = 0;
    e = _set_printf_count_output(1);
    printf( "%%n support was %sabled.\n", e ? "en" : "dis");
    printf( "%%n support is now %sabled.\n", _get_printf_count_output() ? "en" : "dis");
    printf( "12345%n6789\n", &i); // %n format should set i to 5
    printf( "i = %d\n", i);

    return 0;
}

调用_set_printf_count_output函数可以打开%n使能,

#include <stdio.h>

int main(void)
{
    printf("_get_printf_count_output is %d\n", _get_printf_count_output()); // 0
    printf("_set_printf_count_output is %d\n", _set_printf_count_output(1)); // 0
    printf("_get_printf_count_output is %d\n", _get_printf_count_output()); // 1
    printf("_set_printf_count_output is %d\n", _set_printf_count_output(1)); // 1
    printf("_get_printf_count_output is %d\n", _get_printf_count_output()); // 1

    return 0;
}

_set_printf_count_output函数返回当前的printf_count_output结果

以下代码输入结果为

int main(void)
{
    _set_printf_count_output(1);
    
    char c;
    short s;
    int i;
    long l;
    long long ll;
// 最初转换指示符%n是用来帮助排列格式化输出字符串的. 它将字符数目成功地输出到以参数的形式提供的整数地址中
    printf("hello %hhn.", &c);
    printf("hello %hn.", &s);
    printf("hello %n.", &i);
    printf("hello %ln.", &l);
    printf("hello %lln.\n", &ll);
    fprintf(stdout, "c: %hhd, s: %hd, i: %d, l: %ld, ll: %lld\n", c, s, i, l, ll); // 6
    return 0;
}

以下代码输入结果为

int main(void)
{
    char* insertTime = "2021";
    printf("|%-15s|\n",insertTime);     //左对齐,15位长度,不够补空格
    printf("|%15s|\n",insertTime);      //右对齐,15位长度,不够补空格
    printf("|%015s|\n",insertTime);     //右对齐,15位长度,不够补0
    printf("|%-15.2f|\n",atof(insertTime));  //左对齐,15位长度,带两位小数,不够补空格
    float f=123.456;
    printf("%f \n",f);
    printf("%10.1f \n",f);
    printf("%5.1f \n",f);
    printf("%10.3faaa \n",f);
    printf("%-10.3faaa \n",f);

    printf("%g \n",f);
    return 0;
}

|2021           |
|           2021|
|000000000002021|
|2021.00        |
123.456001
     123.5
123.5
   123.456aaa
123.456   aaa
123.456
 

%[标志][宽度][.精度][{长度修饰符}] 转换指示符

例如,对转换规范%-10.8ld来说,-是标志位,10代表宽度,8代表精度,字面l是长度修饰符,d是转换指示符。这个转换规范将一个long int型的参数按照十进制格式打印,在一个最小宽度为10个字符的域中保持最少8位左对齐。每一个域都是代表特定格式选项的单个字符或数字。最简单的转换规范仅仅包含一个”%”和一个转换指示符(例如%s)。

转换指示符:用来指示所应用的转换类型。它是唯一必须的格式域,出现在任意可选格式域之后。下表中列举了C标准中的一些转换指示符:

标志:标志位用来调整输出和打印的符号、空白、小数点、八进制和十六进制前缀等。一个格式规范中可能包含一个或多个标志。

宽度:是一个用来指定输出字符的最小个数的十进制非负整数。如果输出的字符个数比指定的宽度小,就用空白字符补足。如果指定的宽度较小也不会引起输出域的截断。如果转换的结果比域宽大,则域会被扩展以容纳转换结果。如果使用星号(*)来指定宽度,则宽度将由参数列表中的一个int型的值提供。在参数列表中,宽度参数必须置于被格式化的值之前。

精度:是用来指示打印字符个数、小数位或者有效数字个数的非负十进制整数。与宽度域不同,精度域可能会引起输出的截断或浮点值的舍入。如果精度值被设为0并且被转换值也为0,则不会输出任何字符。如果精度域是一个星号(*),那么它的值就由参数列表中的一个int参数提供。在参数列表中,精度参数必须置于被格式化的值之前。

长度修饰符:指定了参数的大小。下表列举了长度修饰符及其对应的含义。如果使用了表中未出现的长度修饰符和转换指示符的组合,则会导致未定义的行为:

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值