考虑代码
#include<stdio.h>
int main(void)
{
char* a;
scanf("%s",a);//&a and &a[0] give same results-crashes
printf("%s",a);
return 0;
}
为什么这段代码导致崩溃?而使用字符数组的代码工作得很好?
#include<stdio.h>
int main(void)
{
char a[100];
scanf("%s",&a[0]);//works fine
printf("%s",a);
return 0;
}
差异是字符数组和指针?但是我知道指针只是指向第一个元素是&amp; a [0]应该工作正常但是高级代码崩溃所有三个是a,&amp; a和&amp;一个[0]? 我要收集的主要内容是,如果我坚持只使用scanf,我该如何输入字符指针? 如果我不清楚,我道歉。 提前谢谢:)
答案 0 :(得分:9)
因为char* a;
在堆栈上为字符指针分配空间,而char a[100];
为100个字符分配空间。
在前一种情况下,您需要为指向指向的指针分配一些实际内存。导致崩溃的原因是a
被设置为某个任意值(您没有初始化它),当您scanf
时,这就是写入数据的地方。如果您只使用a
,那就让我们称之为第一个崩溃类型。
如果你使用&a
,它会将你的输入写在指针本身上,这会给你一个指向who-know-where的指针,导致第二个崩溃类型。这假设你没有输入更多的字符而不是溢出指针 - 这会破坏调用堆栈导致另一个崩溃情况(类型3)。
作为建议,请不要使用没有边界检查的输入函数,除非您完全控制向他们呈现的数据。即使使用char[100]
,有人也可能通过输入比缓冲区中更多的字符来导致代码中的堆栈溢出。
我发现最好的办法是使用fgets
(可以限制读取的字符数)与sscanf
一起使用(尽管如果你得到的只是一个字符串,不需要sscanf
。)
答案 1 :(得分:4)
a
没有任何意义。或者实际上,它是未初始化的,所以它指向某个地方,而不是某个有效的地方。
您可以像已经尝试过的那样在堆栈上提供存储空间:
#include <stdio.h>
int main()
{
char x[100];
char *a = x; // a points to the storage provided by x on the stack
scanf("%s",a); // should work fine
printf("%s",a);
return 0;
}
请注意,printf("%s",x);
会产生完全相同的结果,a
指向x
,因此您的字符串将会“存在”。
或者你可以让内存管理使用malloc
来处理它#include <stdio.h>
#include <stdlib.h>
int main()
{
char *a = malloc (100*sizeof(char)) // a points to the storage provided by malloc
if (a != null)
{
perror ("malloc"); // unable to allocate memory.
return 1;
}
scanf("%s",a); // should work fine
printf("%s",a);
free (a); // just remember to free the memory when you're done with it.
return 0;
}
HTH。
修改的
此外,在评论开始之前...这是非常不安全的代码,但我想你只是试图围绕指针,所以我只是试着给你一个正确方向的推动。 (如果不是,你需要考虑阅读有限数量的数据,确保它适合你的缓冲区,如果它来自一些其他来源而不是文件,你需要确保你得到所有数据,依此类推,等等)。
答案 2 :(得分:2)
在使用a
之前,您必须为malloc()
分配内存。
答案 3 :(得分:2)
scanf需要放置所读字符的位置。您可以向它传递一个指向字符数组的指针(在第二个示例中执行的操作),或者指向以另一种方式获得的某些内存的指针(比如malloc())。在你的第一个例子中,你传递一个未初始化的指针,因此你正在观察的问题。
答案 4 :(得分:1)
在第一个例子中,a是一个“悬空指针” - 它是一个包含某个随机存储位置地址的指针。在大多数情况下,访问此地址将导致崩溃。底线:您需要为a。
分配内存答案 5 :(得分:1)
在第一个代码中,a
是一个未初始化的char指针。
您正在尝试写入未分配的内存或保留的内存。
您需要使用malloc()
为输入字符串分配内存。
int main(void) {
char* s;
/* ... */
s = malloc(100 * sizeof(*s));
if (s == NULL) {
return 1;
/* ... */
}