玩了几个星期后,我现在讨厌它。
我现在正试图使用execl将参数传递给另一个程序,并且参数的格式化做了奇怪的事情:
int select[2], result[2];
char str_w,str_r;
snprintf(&str_w, 2, "%d", select[1]);
snprintf(&str_r, 2, "%d", result[0]);
printf("%d %d %s %s\n", select[1], result[0], &str_w, &str_r);
execl("./recive.x","./recive.x",&str_w,&str_r,(char *)NULL);
这里重要的是snprintf:我正在尝试将向量中的数字转换为字符串。该数字将小于10.当我执行此操作时,显示的printf的结果为:
5 6 6
这意味着select [1]中有一个数字(5),result [0]中有一个数字(6),result [0]正确转换为字符串,但选择[1] no。
这种行为到底是什么!!
提前谢谢!
答案 0 :(得分:2)
对sprintf的调用必须为打印数据提供缓冲区,足以适应整个输出。您正在将指针传递给单个字符,因此输出显然不适合。
char str_w[2];
snprintf(str_w, 2, "%d", select[0]);
将一位数字转换为字符串的更好方法如下:
char res[2];
res[0]=num+'0';
res[1]=0;
请注意第一个零点周围的单引号:想法是将零字符的代码添加到一位数字。
答案 1 :(得分:2)
玩了几个星期后,我现在讨厌它。
这不是一种罕见的反应。我的介绍CS课程的三分之一改变了专业,理由是C的难度(这是一种可怕的教学语言)。我用了好几年的时间来充分包裹它,但是一旦我这样做,我开始欣赏它。
char str_w,str_r;
snprintf(&str_w, 2, "%d", select[1]);
snprintf(&str_r, 2, "%d", result[0]);
这是你的主要问题; str_w
和str_r
只能保留一个char
值,而不是字符串(这需要至少 2个字符)。相反,您需要将str_w
和str_r
声明为char
的数组,大到足以保存最大int
你的字符串表示形式我期待,加上符号的空间(如果值为负),再加上0终结符。例如,如果您没有限制select
或result
上的值:
#define MAX_DIGITS 20 // max decimal digits for 64-bit integer
#define SIZE MAX_DIGITS+2 // 2 extra for sign and 0 terminator
char str_w[SIZE], str_r[SIZE];
sprintf(str_w, "%d", select[1]);
sprintf(str_r, "%d", result[0]);
通过使目标数组足够大以进行任何可能的输入,您不必担心溢出。是的,您会受到一些内部碎片的影响,并且取决于您的应用程序,这可能是也可能不是问题。但我只想保持简单。
如果您知道某个事实您的select
和result
数组永远不会保存0..10范围之外的值,那么您可以将SIZE设置为3(最多2位数加0终结符)。
这意味着select [1]中有一个数字(5),result [0]中有一个数字(6),result [0]正确转换为字符串,但选择[1] no。
这种行为到底是什么!!
由于您将地址传递给不足以保存结果的缓冲区,因此行为是 undefined ,这意味着编译器没有义务警告您正在执行某些操作危险的。
这是最有可能发生的事情(由于行为未定义,任何事件序列都是可能的,但我认为这是对结果的合理解释)。首先,假设您的变量在内存中布局如下:
Item Address Value
---- ------- -----
str_r 0xffec1230 ??
str_w 0xffec1231 ??
0xffec1232 ??
str_w
和str_r
被分配给连续的字节,它们的初始值是不确定的。在第一个snprintf
到str_w
之后,您的记忆现在看起来像这样:
Item Address Value
---- ------- -----
str_r 0xffec1230 ??
str_w 0xffec1231 '5'
0xffec1232 0
snprintf
会将一个尾随的0终结符写入缓冲区;在这种情况下,它将终结符写入str_w
之后的字节。在第二次sprintf
调用之后,内存现在看起来像这样:
Item Address Value
---- ------- -----
str_r 0xffec1230 '6'
str_w 0xffec1231 0
0xffec1232 0
第二次snprintf
调用将{0}终止符写入str_r
之后的字节,恰好是str_w
;你结束了之前写给它的价值。这就是为什么你看到str_r
字符串而不是str_w
字符串的原因。
答案 2 :(得分:0)
使用char
定义唯一的一个字节变量。它必须是char
s。