繁体   English   中英

在scanf中没有`&`的情况下,%s如何在c中工作?

[英]How does %s work in c without `&` in scanf?

我对c中的%s感到有些困惑。 我是编程新手,我正在学习c作为我的拳头PL

%s如何在c中工作。 我发现使用%s时不需要使用&在scanf中。 为什么会这样呢? 为什么我使用时%s给出细分错误

char *a="how are you";
printf("%s",*a);

我已经阅读了此链接:- 在C中正确使用%s-非常基本的水平,但是我想以粗体显示问题的答案。

您需要了解指针与char变量之间的区别。

通常在scanf()传递一个数组以匹配%s说明符,然后在该位置使用指向数组第一个元素的指针。 对于%d等其他说明符,您需要传递目标变量的地址,以允许scanf()将结果存储在其中。

相反, printf()不会在任何地方存储结果,因此它只需要变量的值即可, "%s"说明符除外,该说明符需要终止非'\\0' char值数组的第一个元素的地址由'\\0'

在您的示例中,您传递了一个char变量, printf()将其作为地址并尝试对其进行解除引用,这将导致分段错误,因为它期望该变量是一个充满char并终止的数组的地址带有' 0'


注意printf("%s", *a); 等效于printf("%s", a[0]); 因此,您可以清楚地看到传递给"%s"的变量的类型为char并且printf()将使用(char *) 'h'作为有效指针,执行*(char *) 'h'操作,但大多数情况下可能不会。

声明“在使用%s时不需要使用&在scanf中”可能会误导您。 关于读入和存储值的scanf格式说明符始终需要指向相应类型对象的指针。 这通常是由一元&运算符实现的,该运算符返回对象的地址。 但是某些类型(例如数组)会自动衰减为指向数组第一个元素的指针,因此以下代码实际上会传递一个指针:

char text[100] = "";
scanf("%s", text);  // array automatically decays to a pointer to the first element.
scanf("%s", &text[0]);  // explicitly take the address of the first element

如果您没有数组,而是一个指向char的指针,则代码将更改如下:

char *text2 = malloc(100);
scanf("%s", text2);  // text2 is a pointer, not an array 

同样,您不需要& ,因为您已经传递了指针值。

因此,声明“使用%s时不需要在scanf中使用&”是正确的,因为%s始终需要一个指向字符序列的指针,并且您可以传递一个自动衰减到指针的数组,也可以直接传递一个指针。

从两个角度来看,您的代码是错误的:

char *a="how are you";
printf("%s",*a);

首先, *a不是指针,而是单个字符值(在您的情况下为'h' ),当将其转换为指针值时,它将类似于内存地址0x0000001A 对此进行访问会产生未定义的行为/ seg错误。

其次,它是一个printf ,而不是scanf 如果需要printf,请输入:

char *a="how are you";
printf("%s",a);

如果需要scanf,请输入:

char a[100];;
scanf("%s",a);

scanf()函数将指针指向字符数组的第一个元素,并将其作为%s伪指令的参数。 由于数组标识符会衰减到指向数组第一个元素的指针(在大多数表达式中,包括函数调用),因此仅使用不带&地址运算符的数组名称即可提供正确的指针。 实际上,在此处使用&运算符是错误的。

给定代码:

char array[100];
int ret_val = scanf("%99s", array);

在这里,标识符array衰减为指向array[]的第一个元素的指针,这是scanf()期望的。 如果相反,这是:

int ret_val = scanf("%99s", &array);

这是不正确的,因为&array是指向数组array[]的指针。 区别在于, array衰减到一个指向一个字节的指针,而&array是指向100个字节的指针(在这种情况下)。 例如,当涉及指针算术时,这种差异很重要。

在第二个示例中:

char *a = "how are you";
printf("%s", *a);

在这里, a已经是一个指向数组第一个元素的指针(因为a是一个指向char的指针,而"how are you"是一个字符串文字,在内存中表示为以char结尾的空终止数组),该数组递归为一个指针。表达式中此数组的第一个元素)。 通过使用*a代替a ,将值'h'用作printf()的参数,而不是预期的指针,从而导致未定义的行为。

另外,请注意,在我的第一个示例中, scanf()的返回值存储在int变量ret_val scanf()返回成功分配的次数,并且应该在健壮的代码中检查此值。 此外,请注意,将%sscanf()一起使用时,应始终指定最大宽度,以避免缓冲区溢出。 在这里,使用%99s ,在数组末尾留出空终止符( \\0 )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM