当我使用sprintf
函数以某种方式改变变量A
的值时,会怎样?
#include <stdio.h>
int main(void) {
short int A = 8000;
char byte_1[2] /*0001 1111 01000 0000*/, total[4];
sprintf(byte_1, "%i", A);
printf("%s\n", byte_1);// displayed on the screen 8000
printf("%i\n", A); // displayed on the screen 12336
}
答案 0 :(得分:8)
(100, 200, 300, 400)
太短,无法用十进制表示byte_1
的表示形式:它只能有1位数字和空终止符,而A
没有此信息,因此它将尝试在sprintf
数组的末尾进行写操作,从而导致未定义的行为。
byte_1
增大为12个字节是一个好的开始。 byte_1
本质上是不安全的。使用sprintf
来防止缓冲区溢出:
snprintf
以下是这种意外输出的可能解释:假设snprintf(byte_1, sizeof byte_1, "%i", A);
位于byte_1
之前的内存中。 A
将sprintf
的值转换为五个字符A
,'8'
,'0'
,'0'
和'0'
'\0'
的值,并覆盖变量byte_1
本身的值。当您以后用A
打印A
的值时,printf
不再具有值A
,而是8000
...只是无限范围之一未定义行为的可能影响。
尝试使用此更正版本:
12336
答案 1 :(得分:3)
存储在A
中的值的文本表示形式为”8000”
-这是四个字符加字符串终止符,因此byte_1
必须为至少 5个字符宽。如果要byte_1
存储任何无符号int的表示形式,则应使其更像12个字符宽:
char byte_1[12];
两个字符不足以存储字符串”8000”
,因此当sprintf
写入byte_1
时,这些多余的字符很可能会覆盖A
。
还要注意,无符号int的正确转换说明符是%u
,而不是%i
。当尝试格式化设置了最高有效位的非常大的无符号值时,这将很重要。 %i
将尝试将其格式化为负号。
修改
正如chrqlie所指出的,OP宣布A
为short int
–由于某种原因,另一个答案已将其更改为unsigned int
,并且一直困扰着我。严格来说,如果要带符号的十进制输出,则short int
的正确转换说明符是%hd
。
为便于记录,以下是一些常见的转换说明符及其相关类型的列表:
Specifier Argument type Output
--------- ------------- ------
i,d int Signed decimal integer
u unsigned int Unsigned decimal integer
x,X unsigned int Unsigned hexadecimal integer
o unsigned int Unsigned octal integer
f float, double Signed decimal float
s char * Text string
c char Single character
p void * Pointer value, implementation-defined
对于short
和long
类型,有一些长度修饰符:
Specifier Argument type Output
--------- ------------- ------
hd short signed decimal integer
hhd char signed decimal integer
ld long signed decimal integer
lld long long signed decimal integer
这些相同的修饰符可以应用于u
,x
,X
,o
等。
答案 2 :(得分:0)
byte_1
对于“ A”的四位数而言太小。它只有一个位数和空(\0
)终止符的空间。如果您将byte_1
做成5个字节的数组,每个数字1个位,空字节,则可以容纳“ A”。
#include <stdio.h>
int main(void) {
unsigned int A = 8000;
char byte_1[5], total[4];
sprintf(byte_1, "%i", A);
printf("%s\n", byte_1);
printf("%i\n", A);
return 0;
}
基本上,搞乱内存并试图将值放入对它们来说太小的变量是未定义的行为。这是合法的,但从客观上讲在C语言中是危险的,任何程序都不应像这样访问内存。
答案 3 :(得分:-5)
sprintf(byte_1, "%i", A);
格式说明符需要同意变量类型。
我建议进行以下更改:
sprintf(byte_1, "%c", A);
printf("%c\n", byte_1);
A
,使其与byte_1
具有相同的类型。这将迫使您更改示例中的值以匹配char类型的范围。请注意,使用函数来保护您的溢出只是一个不好的解决方案。相反,作为此代码的设计师,您的责任是为该工作选择合适的工具。使用char变量时,需要使用类似于char的容器。整数,浮点数,字符串等也一样。如果您有1公斤的糖,则要使用1公斤的容器来容纳此数量。如您所见,您不会使用杯子(250g),因为杯子会溢出。在C中编码愉快!