很抱歉,如果这是一个愚蠢的问题,但是我遇到一个问题,即我数组中的所有元素都被设置为C中的最后一个元素。我想我正在重写某些东西,并且想要另一双眼睛。我的目标是创建一个随机类型为char类型的数组。代码如下:
int main(int argc, char *argv[]) {
unsigned int seed = atoi(argv[1]);
printf("seed = %d\n", seed);
srand(seed); //NOTE: i seed random from the command line
unsigned char *p[8];
for(int i = 0; i < 8; i++){
int random_number = rand() % 255;
char random_number_string[8];
itoa(random_number, random_number_string, 10);
p[i] = random_number_string;
//below is just to check
printf("p[%d] = %s\n", i, p[i]);
}
// below i comment out irrelevant parts of the code
//unsigned char byte0[8];
//itoa( (rand() % 256), byte0, 10);
//printf("byte0 = %s\n", byte0);
//printf("Binary values: \n");
for(int n = 0; n < 8; n++){
printf("p[%d] = %s\n", n, p[n]);
//PRINTBIN((int)p[i]);
//printf("\n");
}
return 0;
所有这些的结果是:
seed = 1054480
p[0] = 81
p[1] = 66
p[2] = 36
p[3] = 32
p[4] = 81
p[5] = 245
p[6] = 33
p[7] = 72
p[0] = 72
p[1] = 72
p[2] = 72
p[3] = 72
p[4] = 72
p[5] = 72
p[6] = 72
p[7] = 72
我只是想知道我正在做些什么来掩盖所有这些价值观。谢谢。
答案 0 :(得分:2)
在您的代码中,p是8个指向char的指针的“数组”。这意味着您将在数组p中存储一个地址位置。 如果您像这样打印地址和数据-
printf("p[%d] = %s\n", i, p[i]);
printf("%d\n", p[i]);
您会注意到,数组(p)中的所有值都是相同的,即数组中的所有元素都是“相同”的,这恰好是第二个for()循环输出的结果。该地址是局部变量random_number_string的地址。 第一个循环将打印不同的数据,因为第一个循环将在每次迭代中更改数据,并且在最后一次迭代后,此地址位置包含“ last”值集。
希望这可以澄清您所看到的行为。
答案 1 :(得分:0)
第一个循环的每次迭代都会创建其本地char random_number_string[8];
数组的新实例,然后在末尾销毁它。在该循环的每次迭代中,您将在random_number_string
中存储指向该p[i]
数组开头的指针。每个指针p[i]
在每次第i
次迭代的结尾都变成“酸”(悬挂)。因此,所有p[i]
值最终都无效。任何尝试访问这些值的操作都将导致未定义的行为。
这正是您第二个周期所做的。您的程序的行为是不确定的。
注意,顺便说一句,说所有数组元素都指向相同的内存位置是不正确的(就像这里的一些答案一样)。您的数组p
包含无效和不确定的指针值。关于这些值,无话可说。
答案 2 :(得分:0)
您的第一个循环的每次迭代都定义了'char random_number_string [8]',为此空间从堆栈帧中分配。每次迭代都不会增加堆栈帧的大小,但是会重用与先前迭代相同的堆栈空间,这意味着在random_number_string周围的每次都将在完全相同的地址处找到。并且由于您将random_number_string的地址放入“ p”数组的每个元素中,因此每个元素都具有相同的值。无论您放置在该地址的什么内容,都将由数组中的每个元素指向。
但是还有另一个问题,就是您的代码。您已经将自动变量的地址放置在另一个数据结构中,问题在于,包含random_number_string的堆栈帧在第一个循环的每次迭代结束时从堆栈中弹出,并将被后续的堆栈帧/代码块重用。
如果您事先知道所有这些字符串的最大大小,则可以简单地使用二维数组预先分配其中的大部分。这是用这种方法编写的代码:
int main(int argc, char *argv[]) {
unsigned int seed = atoi(argv[1]);
printf("seed = %d\n", seed);
srand(seed); //NOTE: i seed random from the command line
unsigned char p[8][10];
for(int i = 0; i < 8; i++){
int random_number = rand() % 255;
itoa(random_number, p[i], 10);
printf("p[%d] = %s\n", i, p[i]);
}
for(int n = 0; n < 8; n++){
printf("p[%d] = %s\n", n, p[n]);
}
return 0;
}
或者,您可以动态地(从堆中)分配它们。完成程序后,可能需要释放它们,具体取决于您的程序。
int main(int argc, char *argv[]) {
unsigned int seed = atoi(argv[1]);
printf("seed = %d\n", seed);
srand(seed); //NOTE: i seed random from the command line
unsigned char *p[8];
for(int i = 0; i < 8; i++){
int random_number = rand() % 255;
p[i] = (unsigned char *)malloc(10 * sizeof(unsigned char));
itoa(random_number, p[i], 10);
printf("p[%d] = %s\n", i, p[i]);
}
for(int n = 0; n < 8; n++){
printf("p[%d] = %s\n", n, p[n]);
}
return 0;
}