我在这段代码中使用了一个数组,因为我需要一个应该总是被修改的字符串,这就是为什么我没有使用指针,每次运行代码我都会得到一个在第31次迭代中的奇怪行为。
代码
int i = 0;
char name[100];
srand(getpid());
while(i<100) {
name[i] += (char)'A'+(rand()%26);
printf("%d strlen\n", i+1);
printf("%s\n", name);
printf("/////\n");
i++;
}
输出
/////
30 strlen
IKXVKZOLKHLTKBFFTUZCYXHYVEBZOY
/////
31 strlen
IKXVKZOLKHLTKBFFTUZCYXHYVEBZOYJ
/////
32 strlen
IKXVKZOLKHLTKBFFTUZCYXHYVEBZOYJWttime
/////
33 strlen
IKXVKZOLKHLTKBFFTUZCYXHYVEBZOYJW�time
/////
34 strlen
IKXVKZOLKHLTKBFFTUZCYXHYVEBZOYJW��ime
/////
35 strlen
IKXVKZOLKHLTKBFFTUZCYXHYVEBZOYJW���me
/////
36 strlen
IKXVKZOLKHLTKBFFTUZCYXHYVEBZOYJW����e
/////
37 strlen
IKXVKZOLKHLTKBFFTUZCYXHYVEBZOYJW�����
换句话说,它总是打印ttime
作为第31个字符,然后代码覆盖该单词的每个字符,结果我得到问号。
继续观察最终输出的情况会更糟糕
100 strlen
IKXVKZOLKHLTKBFFTUZCYXHYVEBZOYJW�����K��ȶ������MKRLHALEV�SNNRVWNOEXUVQNJUHAEWN�W�YPMCW�N�PXHNT��0�
/////
为什么会这样?
答案 0 :(得分:1)
嗯,你正在打印垃圾值。行为将是未知的。(未定义的行为)我的意思是,可能是这些垃圾值(随随机数添加)可能是某些字符的ascii值或者可能是某些非printables的情况。你应该初始化char数组(使用\0
' - 这将有两个目的,为正在运行的字符串提供\0
,你也可以添加并确保它是可打印的)或只需分配。
name[i] = 'A'+(rand()%26);
还在字符串的末尾添加\0
。否则它将尝试访问数组索引超出绑定,直到找到\0
并且它将调用未定义的行为。
31
不是特别的东西 - 下次你运行时它可以是任何东西。
代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void) {
size_t i = 0;
char name[100]={0}; // = "";
srand(getpid());
while(i<99) { // till 99 making sure you won't overwrite the last NUL
name[i] ='A'+(rand()%26);
printf("%d strlen\n", i+1);
printf("%s\n", name);
printf("/////\n");
i++;
}
return 0;
}
请注意,我们已经循环到98
索引,因为99
索引中存在NUL终止字符。
答案 1 :(得分:1)
char name[100];
不是字符串。它只是另一个100元素char
数组。
在C中,字符串是 始终 ,其中包含(至少)一个'\0'
字符以标记字符串的结尾。 printf()
,大多数str*()
个函数和许多其他函数都依赖于此终止'\0'
。
添加数组元素背后的想法是什么?
name[i] += ...
他们的价值没有设定,他们是垃圾。甚至值得,添加它们意味着读取未初始化的内存1,这反过来引发未定义的行为。
因此,要修复代码,请手动添加终结符:
while (i < 99) {
name[i] = (char) 'A' + (rand() % 26);
name[i + 1] = '\0';
或者在开始之前对所有name
初始化'\0'
进行懒惰处理:
char name[100] = ""; /* or ... = {0}; */
(这可以让你坚持做name[i] += ...
。但是,由于所有元素都是0
,添加是没有用的。)
在 任何 的情况下,不要循环直到数组的最后一个元素(此处为100),但总是少一个作为最后一个元素保留用于终止{{1} }。
答案 2 :(得分:0)
如果char name[100]
数组是函数内的局部变量,则其初始值未定义。所以它将包含之前在那块内存中的随机垃圾。
因此当你做
时name[i] += (char)'A'+(rand()%26);
你实际上在做什么
name[i] = RANDOM JUNK + (char)'A'+(rand()%26);