我在这段代码中使用了一个数组,因为我需要一个应该总是被修改的字符串,这就是我不使用指针的原因,每次运行代码时我都会在第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�
/////
为什么会这样?
那么你是打印垃圾价值。行为将是未知的。(未定义的行为)我的意思是,可能是这些垃圾值(随随机数添加)可能是某些字符的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
th索引,因为在99
th索引中有NUL终止字符。
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),但总是少一个,因为最后一个元素是为终止'\0'
保留的。
如果char name[100]
数组是函数内的局部变量,则其初始值未定义。所以它将包含之前在那块内存中的随机垃圾。
所以当你这样做的时候
name[i] += (char)'A'+(rand()%26);
你其实在做
name[i] = RANDOM JUNK + (char)'A'+(rand()%26);