提问人:Hai Pham 提问时间:9/12/2023 最后编辑:Hai Pham 更新时间:9/13/2023 访问量:75
函数在 C 语言中返回字符串和 frintf() 行为
Function return a string and frintf() behavior in C language
问:
我正在学习如何在 C 中返回字符串。它有 2 种方式:使用静态字符数组或使用 malloc。我对源代码进行了一些实验,例如:
#include <stdio.h>
#include <stdlib.h>
char *repeat(char r)
{
int x;
// char *string = malloc(32 * sizeof *string);
static char string[32];
for(x=0;x<32;x++)
string[x] = r;
return string;
}
int main()
{
char *a = repeat('a');
printf("%s\n",a);
printf("%s\n",repeat('a'));
return(0);
}
我知道此代码将具有未定义的行为,因为字符串末尾没有“\0”字符。如果我使用静态变量方式,则在调用的 2 次 printf() 函数中输出相同:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa☺
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa☺
但是当我使用 malloc 方式时,结果是:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaasers\man∩╒║2ü8
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
根据我的理解,f() 函数会返回分配给字符串的地址,并且由于字符串不是以 '/0' 结尾的,所以 printf() 函数会打印一些垃圾字符,就像 in 语句一样。但是在声明中,没有打印垃圾字符,我无法确定导致这种行为的原因。printf("%s\n",a)
printf("%s\n",repeat('a'))
有人可以帮我解释一下吗?
编辑:我只是好奇 f() 函数和 printf() 函数返回的指针值是如何工作的,从而导致两个打印结果的差异。我多次尝试在 malloc() 情况下运行程序,并且始终使用语句的结果始终没有任何垃圾字符。 printf("%s\n",repeat('a'))
答:
一旦代码调用了未定义的行为,任何(次数)执行的特定结果都不能以任何方式证明是合理的。从语言一致性的角度来看,它只是未定义。
溶液:不要编写违反语言定律的代码并调用未定义的行为。
评论
您的代码包含
// char *string = malloc(32 * sizeof *string);
static char string[32];
使用静态变量时,函数的返回值将始终是此静态数组变量所在的内存中的相同地址。数组最后一个元素之后的内存内容可能属于不同的静态或全局变量。因此,如果您不修改位于那里的任何内容,则很可能在每次调用函数时都获得相同的内存内容。
您的使用方式将在每次调用函数时分配新的内存,而您的代码不会占用内存,因此您每次都会在不同的地址获得内存。在这种情况下,您可能会获得不同的内存内容。malloc
free
可以将版本更改为仅分配一次内存。在这种情况下,您可能会在每次调用函数时看到相同的结果。malloc
例:
static char *string = NULL;
if(!string) string = malloc(32 * sizeof *string);
是否看到垃圾字符取决于在数组末尾之后恰好找到 () 字节的位置。NUL
'\0'
如果使用且不使用任何内存分配内存,则分配的阵列大小之后的内存内容可能包含所有 0,因为在打开系统后,未使用的内存可能会初始化为 0。如果内存,则可能会看到内存分配函数之前存储在预先分配的内存中的部分数据或内存分配函数使用的内部数据。但是,您也可以看到以前运行过的程序留下的垃圾数据。malloc
free
free
所有这些都取决于实现,您可能会在重复调用程序时看到不同的行为。这就是为什么我写了“可能”、“可能”、“可能”和“可能”。即使它看起来工作正常,这也是未定义的行为。
评论
return string;
string[sizeof string - 1] = 0;
free()
repeat()
printf()
'\0'
malloc()
free()
printf()
printf