用scanf读取字符串
我有点困惑。我的印象是,使用用scanf读取字符串,c,scanf,C,Scanf,我有点困惑。我的印象是,使用scanf()读取C字符串的正确方法是 (不要介意可能的缓冲区溢出,这只是一个简单的例子) 但是,下面的方法似乎也能奏效 scanf( "%s" , &string ); 这仅仅是我的编译器(gcc)、纯粹的运气还是别的什么?数组“衰减”为指向其第一个元素的指针,因此scanf(“%s”,string)相当于scanf(“%s”,&string[0])。另一方面,scanf(“%s”,&string)传递一个指向-char[256]的指针,但它指向相同的位置
scanf()
读取C字符串的正确方法是
(不要介意可能的缓冲区溢出,这只是一个简单的例子)
但是,下面的方法似乎也能奏效
scanf( "%s" , &string );
这仅仅是我的编译器(gcc)、纯粹的运气还是别的什么?数组“衰减”为指向其第一个元素的指针,因此scanf(“%s”,string)
相当于scanf(“%s”,&string[0])
。另一方面,scanf(“%s”,&string)
传递一个指向-char[256]
的指针,但它指向相同的位置
然后,scanf
在处理其参数列表的尾部时,将尝试拉出一个char*
。当您传入string
或&string[0]
时,这是正确的,但是当您传入&string
时,您依赖于语言标准不能保证的东西,即指针&string
和&string[0]
——指向从同一位置开始的不同类型和大小的对象的指针——以相同的方式表示
我不相信我曾经遇到过一个系统,在这个系统上不工作,实际上你可能是安全的。尽管如此,这是错误的,它可能会在某些平台上失败。(假设的例子:一个“调试”实现,它包含每个指针的类型信息。我认为符号“Lisp机器”上的C实现是这样做的。)我认为下面的内容是准确的,可能会有所帮助。 如果发现任何错误,请随时更正。我是C的新手
char str[]
'\0'
&str
,&str[0]
和str
,这三个字符都表示内存中相同的位置,即数组str
的第一个元素的地址
char*strprtr=&str[0]//声明和初始化char *strPtr; strPtr = &str[0];
strPtr
是指向char
strprprtr
指向数组str
strPtr
是一个在内存中有自己地址的变量strprprtr
是一个存储地址值的变量&str[0]
strprpr
内存中自己的地址与它存储的内存地址不同(内存中数组的地址a.k.a&str[0])&strPtr
表示strPtr本身的地址char **vPtr = &strPtr;
声明并用strprtr指针的地址初始化
或者,您可以将其拆分为两部分:
char **vPtr;
*vPtr = &strPtr
*vPtr
指向strPtr指针*vPtr
是一个在内存中有自己地址的变量*vPtr
是一个存储地址和strprtr值的变量str++
,str
地址是一个const
,但是
您可以执行strPtr++
在第二种情况下,实际上没有可能的缓冲区溢出,因为您根本没有使用该缓冲区。或者你可以说任何大于3个字符的字符串都会溢出你的“缓冲区”。另外,其他人已经指出了这里发生的事情。试过了,加雷斯是对的。奇怪。因为这个问题是通过搜索“如何使用scanf读取字符串”返回的,所以应该指出,这个问题是关于如何将指向缓冲区的指针传递到
scanf
,问题和公认的答案都集中在这一点上,并且省略了在实际代码中应该使用的最大输入长度的重要限制(但这些限制不是这个问题的重点)。
char **vPtr;
*vPtr = &strPtr