#include<stdio.h>
#include<stdlib.h>
void main()
{
char *arr;
arr=(char *)malloc(sizeof (char)*4);
scanf("%s",arr);
printf("%s",arr);
}
在上面的程序中,我真的需要分配arr吗?即使不使用malloc,它也给了我结果。我的第二个疑问是" 我预计第 9 行会出现错误,因为我认为它一定是 printf("%s",*arr(;什么的。
我真的需要分配 ARR 吗?
是的,否则您将取消引用未初始化的指针(即写入随机内存块(,这是未定义的行为。
我真的需要分配 ARR 吗?
您需要通过调用 malloc
或将其设置为指向另一个数组来设置arr
指向您拥有的内存块。 否则,它指向您可能可以访问也可能无法访问的随机内存地址。
在 C 语言中,不鼓励强制转换 malloc
的结果1;这是不必要的,在某些情况下,如果您忘记包含stdlib.h
或没有用于malloc
范围的原型,可能会掩盖错误。
我通常建议malloc
调用写成
T *ptr = malloc(N * sizeof *ptr);
其中T
是你正在使用的任何类型,N
是你想要分配的该类型的元素的数量。 sizeof *ptr
等效于sizeof (T)
,所以如果你更改了T
,你就不需要在malloc
调用本身中复制该更改。 只需减少一次维护头痛。
即使不使用malloc,它也给了我结果
由于未在声明中显式初始化它,因此 arr
的初始值不确定为 2;它包含一个随机位字符串,该字符串可能对应于也可能不对应于有效的可写地址。 尝试通过无效指针读取或写入的行为是未定义的,这意味着编译器没有义务警告您正在执行危险操作。 未定义行为的可能结果是,您的代码似乎按预期工作。 在这种情况下,看起来您正在访问一个随机的内存段,该内存恰好是可写的,不包含任何重要内容。
我的第二个疑问是"我预计第 9 行会出现错误,因为我认为它必须是 printf("%s",*arr(; 或其他什么。
%s
转换说明符告诉printf
相应的参数是类型 char *
,所以printf("%s", arr);
是正确的。 如果您使用了%c
转换说明符,那么是的,您需要使用 *
运算符或下标(例如 printf("%c", *arr);
或 printf("%c", arr[i]);
(取消引用arr
。
此外,除非编译器文档明确将其列为有效签名,否则不应将main
定义为void main()
;请使用int main(void)
或int main(int argc, char **argv)
。
1. C++ 中需要强制转换,因为C++不允许在没有显式强制转换的情况下将
void *
值分配给其他指针类型2. 对于在块范围内声明的指针,情况确实如此。 在文件范围(任何函数外部(或使用
static
关键字声明的指针隐式初始化为 NULL。就个人而言,我认为这是分配内存的一个非常糟糕的例子。
在现代操作系统/编译器中,char *
将占用至少 4 个字节,在 64 位机器上占用 8 个字节。因此,您使用四个字节来存储三个字符串的四个字节的位置。不仅如此,malloc 还会有开销,可能会在实际分配的内存中增加 16 到 32 个字节。因此,我们使用大约 20 到 40 个字节来存储 4 个字节。这比实际需要的要多5-10倍。
代码还强制转换 malloc,这在 C 中是错误的。
由于缓冲区中只有四个字节,scanf
溢出的可能性很大。
最后,没有调用free
将内存返回到系统。
最好使用:
int len;
char arr[5];
fgets(arr, sizeof(arr), stdin);
len = strlen(arr);
if (arr[len] == 'n') arr[len] = ' ';
这不会溢出字符串,并且只使用 9 字节的堆栈空间(不包括任何填充...(,而不是 4-8 字节的堆栈空间和堆上更多。我在数组中添加了一个额外的字符,以便它允许换行符。还添加了代码来删除 fgets 添加的换行符,否则有人会抱怨这一点,我敢肯定。
-
In the above program, do I really need to allocate the arr?
你打赌你会。
-
It is giving me the result even without using the malloc.
当然,这是完全可能的... arr
是一个指针。它指向内存位置。在你对它做任何事情之前,它是未初始化的......所以它指向一些随机内存位置。这里的关键是它指向的地方是你的程序不保证拥有的地方。这意味着您可以只执行scanf()
,并且在arr
指向的随机位置,该值将消失,但另一个程序可以覆盖该数据。
当你说malloc(X)
时,你是在告诉计算机你需要X字节的内存供你自己使用,其他人都不能碰。然后,当arr
捕获数据时,它将安全地供您使用,直到您调用free()
(您忘记在程序中执行此操作BTW(
这是一个很好的例子,说明为什么在创建指针时应始终初始化指向NULL
的指针...它提醒您,您不拥有他们所指向的内容,最好在使用它们之前向他们指出有效的东西。
-
I am expecting an error in 9th line because I think it must be printf("%s",*arr)
不對。 scanf()
想要一个地址,这就是arr
所指向的,这就是为什么你不需要这样做:scanf("%s", &arr)
。printf 的 "%s" 具体器想要一个字符数组(指向字符串的指针(,这又是arr
,所以不需要尊重。