我对某些事情有点困惑。我的印象是,用scanf()
读取C字符串的正确方法是
(不用担心可能的缓冲区溢出,这只是一个简单的例子)
char string[256];
scanf( "%s" , string );
但是,以下似乎也有效,
scanf( "%s" , &string );
这只是我的编译器(gcc),纯粹的运气还是别的什么?
答案 0 :(得分:124)
数组“衰减”为指向其第一个元素的指针,因此scanf("%s", string)
等同于scanf("%s", &string[0])
。另一方面,scanf("%s", &string)
将指针传递给char[256]
,但它指向同一位置。
然后scanf
,当处理其参数列表的尾部时,将尝试拉出char *
。当你通过string
或&string[0]
时,这是正确的事,但是当你传入&string
时,你依赖于语言标准不能保证的东西,即指针&string
和&string[0]
- 指向不同类型和大小的对象的指针,从同一个地方开始 - 以相同的方式表示。
我不相信我曾经遇到过一个不起作用的系统,实际上你可能很安全。尽管如此,这是错误的,它可能会在某些平台上失败。 (假设示例:一个“调试”实现,其中包含每个指针的类型信息。我认为符号系统“Lisp Machines”上的C实现做了类似的事情。)
答案 1 :(得分:-7)
我认为以下内容是准确的,可能有所帮助。 如果您发现任何错误,请随时更正。我是C的新人。
char str[]
包括终止空字符'\0'
&str
,&str[0]
和str
,这三个表示内存中相同的位置,即第一个元素的地址数组str
char * strPtr =& str [0]; //声明和初始化
或者,您可以将其拆分为两个:
char *strPtr; strPtr = &str[0];
strPtr
是指向char
strPtr
点数组str
strPtr
是一个在内存中有自己地址的变量strPtr
是一个存储地址&str[0]
strPtr
自己的地址与它存储的内存地址不同(内存中的数组地址a.k.a& str [0])&strPtr
代表strPtr本身的地址我认为您可以将指针指针声明为:
char **vPtr = &strPtr;
使用strPtr指针的地址声明并初始化
或者你可以分成两部分:
char **vPtr;
*vPtr = &strPtr
*vPtr
指向strPtr指针*vPtr
是一个在内存中有自己地址的变量*vPtr
是一个存储地址& strPtr str++
,str
地址是const
,但是
你可以做strPtr++