printf 没有正确显示我的字符串 - 为啥?
Posted
技术标签:
【中文标题】printf 没有正确显示我的字符串 - 为啥?【英文标题】:printf doesn't display my string correctly - why?printf 没有正确显示我的字符串 - 为什么? 【发布时间】:2021-10-04 12:42:10 【问题描述】:这是我的代码
int wordSize = 8; // defining a word size
int *myArray = NULL;
myArray = malloc(sizeof(char)*(wordSize+1)); // using malloc() so I always have a big enough array should wordSize change. Also to practice.
int index = 0; // defining a variable to browse through myArray
do
myArray[index] = '*';
index++;
while(index < wordSize);
myArray[wordSize] = '\0'; // filling myArray with '*' character and the null terminator /0
printf("%s", myArray); // trying to display myArray, only a single '*' is printed
printf("\n\n");
int i=0;
while(i < wordSize+1)
printf("%c", myArray[i]);
i++;
// trying to display myArray with an other method, this time with success
自从
char string[] = "hello";
printf("%s", string);
工作得很好,我不明白为什么printf("%s", myArray);
不工作,只显示一个*
。 do/while 循环按预期显示 8 *
,这意味着我的数组已按应有的方式填充。
编辑:按照 cmets 的要求,简化了我的示例,并尝试了一些解决方案和其他一些可能性。
【问题讨论】:
*displayedSecretWord[characterCount] = '\0';
是错误的,因为它试图访问索引为characterCount
的元素,但malloc(sizeof(int)*characterCount);
只为从0 到characterCount
−1 的索引分配了足够的内存。除此之外,编辑问题以提供minimal reproducible example。
"This is because when my basic game will be working I want to be able to randomly choose from a list of words, so I can't have a fixed array."
-- 你可以有一个强制的最大字长,然后你也可以有一个固定大小的数组。但是,如果您愿意,当然也可以使用malloc
。
如果你想要一个字符数组,那你为什么要创建一个整数数组呢?每次增加指针时,它都会移动 4 个字节(sizeof int),因此您跳过了 3 个字符。
【参考方案1】:
我认为这是问题所在。
int *myArray = NULL;
...
printf("%s", myArray);
您正在尝试打印一个整数数组,就好像它是一个字符串一样。我认为,通过将错误类型的变量传递给printf()
,您将调用未定义的行为。您只为wordSize+1
字节分配了足够的内存,然后继续将值写入数组,就好像它对wordSize+1
整数足够大一样,这也是有问题的。
通过更改 myArray
的定义来解决此问题:
char *myArray = NULL;
访问此数组成员的其余代码现在应该从写入int
值更改为写入char
值。需要明确的是,我认为您不需要更改任何内容。一旦myArray
被正确定义为char
的数组,编译器就会为您完成。
预计到达时间: 详细了解原始代码中发生的情况。
最初,您分配 9 个字节。这个空间足以容纳略多于 2 个整数(假设 sizeof(int)
为 4)。我还假设这个内存最初是用零填充的。
分配给myArray
的内存如下所示:
myArray[0] 00 00 00 00
myArray[1] 00 00 00 00
myArray[2] 00
然后你遍历并在内存中存储 8 个 '*' 字符,这使内存看起来像这样:
myArray[0] '*' 00 00 00
myArray[1] '*' 00 00 00
myArray[2] '*'
请注意,另外五个星号会写入您不拥有的内存中。
然后在为myArray
分配的内存之外写入一个“终止零”。
然后,您将myArray
(即myArray
中第一个字节的地址)传递给printf()
。您使用了%s
格式说明符,因此它将打印一个字符串。在它打印出第一个字节(一个星号)之后,它看到的下一个字节是零,所以它停止了。
最后,您可以访问myArray
的各个整数成员,就好像它是一个由八个整数组成的数组一样(即使没有足够的内存来容纳三个)。这意味着,代码将与myArray[0]
对应的四个字节读入一个临时整数,并将其值作为字符打印(因为%c
格式说明符传递给printf()
)。随着循环的继续,稍后的内存区域会被读取,包括不属于您的内存。观察到的结果是星号还在你写的地方。
请注意,这一切都是基于对您的开发环境、目标架构等的假设。您观察到的确切机制可能很有趣——但重要的是要记住,这都是未定义行为的所有示例。您不应该依赖它,因为在不同的系统或不同的日子,结果可能会完全不同。
【讨论】:
感谢您的解释。现在,有两件事:1)myArray 是一个指针,那么为什么它是 int 或 char 很重要,如果这不是我们正在修改的内容? 2)为什么循环在显示 myArray 时仍然有效,即使它是 int 而 printf 不是? 你的 ETA 说得很清楚,非常感谢!【参考方案2】:如果 testCharacter 初始化为 0 我认为您应该对显示的SecretWord 使用字符指针类型 然后为displayedSecretWord分配sizeof(char) * (characterCount+1)。
【讨论】:
以上是关于printf 没有正确显示我的字符串 - 为啥?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的 UITableView 单元格的渐变子层没有正确显示?
Android - 为啥 Recycler 视图未显示在设备上? .我认为我的代码是正确的,但视图没有显示