如果我使用“&"会发生什么?在 scanf 函数中使用字符串? [英] What happens if I use "&" with string in scanf function?

查看:42
本文介绍了如果我使用“&"会发生什么?在 scanf 函数中使用字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚在博客中看到了一些代码.它使用了

I just saw some code in a blog. It used

scanf("%s",&T);

但正如我们所知,我们不应该在字符串中使用&符号,因为它会自动分配该字符串的第一个地址.我确实运行了该代码,令人惊讶的是它正在运行,所以我想知道当我在字符串中使用 & 时会发生什么?

but as we know, we shouldn't use ampersand with a string because it automatically assigns the first address of that string. I did run that code, and surprisingly it is working, so I want to know what happens when I use & in string?

#include <stdio.h>
int main()
{
    char T[2];
    scanf("%s", &T);
    printf("You entered %s\n", T);
}

推荐答案

代码片段的相关部分是:

The relevant part of the code snippet is:

char T[2];
scanf("%s", &T);

&T 是一个指向两个字符数组的指针(char (*)[2]).这不是 scanf 用于 %s 说明符所需的类型:它需要一个指向字符的指针 (char *).所以程序的行为是未定义的.

&T is a pointer to the array of two characters (char (*)[2]). This is not the type that scanf needs for a %s specifier: it needs a pointer to a character (char *). So the behavior of the program is undefined.

如您所知,编写此程序的正确方法是

The correct way to write this program, as you know, is

char T[2];
scanf("%s", T);

由于 T 是一个数组,当它在大多数上下文中使用时,它会衰减"到指向第一个字符的指针:T 等价于 &(T[0]) 类型为 char *.当您获取数组的地址 (&T) 或其大小 (sizeof(T)) 时,不会发生这种衰减.

Since T is an array, when it is used in most contexts, it "decays" to a pointer to the first character: T is equivalent to &(T[0]) which has the type char *. This decay does not happen when you take the address of the array (&T) or its size (sizeof(T)).

实际上,几乎所有平台都对指向同一地址的所有指针使用相同的表示.因此,编译器为 T&T 生成完全相同的代码.有一些罕见的平台可能会生成不同的代码(我听说过它们,但我无法命名).一些平台对字节指针"和字指针"使用不同的编码,因为它们的处理器本机寻址的是字,而不是字节.在此类平台上,指向同一地址的 int *char * 具有不同的编码.这些类型之间的转换会转换值,但在诸如可变参数列表之类的东西中误用会导致错误的地址.但是,我希望这样的平台对字符数组使用字节地址.还有一些罕见的平台,其中指针不仅编码数据的地址,还编码一些类型或大小信息.然而,在这样的平台上,类型和大小信息必须是等效的:它是一个 2 字节的块,从 T 的地址开始,并且可以逐字节寻址.所以这个特定的错误不太可能产生任何实际影响.

In practice, almost all platforms use the same representation for all pointers to the same address. So the compiler generates exactly the same code for T and &T. There are some rare platforms that may generate different code (I've heard of them but I couldn't name one). Some platforms use different encodings for "byte pointers" and "word pointers", because their processor natively addresses words, not bytes. On such platforms, an int * and a char * that point to the same address have different encodings. A cast between those types converts the value, but misuse in something like a variable argument list would result in the wrong address. I would expect such platforms to use byte addresses for a char array, however. There are also rare platforms where a pointer encodes not only the address of the data, but also some type or size information. However, on such platforms, the type and size information would have to be equivalent: it's a block of 2 bytes, starting at the address of T, and addressable byte by byte. So this particular mistake is unlikely to have any practical impact.

请注意,如果您首先使用指针而不是数组,情况将完全不同:

Note that it would be completely different if you had a pointer instead of an array in the first place:

char *T; // known to point to an array of two characters
scanf("%s", &T); // bad

这里的 &T 是指向内存中包含字符数组地址的位置的指针.所以 scanf 会在指针 T 存储在内存中的位置写入它读取的字符,而不是在 T 指向的位置.大多数编译器会分析 printfscanf 等函数的格式字符串,因此会发出错误消息.

Here &T is a pointer to the location in memory that contains the address of the character array. So scanf would write the characters that it reads at the location where the pointer T is stored in memory, not at the location that T points to. Most compilers analyze the format string of functions like printf and scanf and so would emit an error message.

请注意,char T[2] 只有两个字符的空间,这包括字符串末尾的空字节.所以 scanf("%s", T) 只能读取一个字符.如果此时输入包含多个非空白字符,程序将溢出缓冲区.要读取单个字符并使其成为单字符字符串,请使用

Note that char T[2] only has room for two characters, and this includes the null byte at the end of the string. So scanf("%s", T) only has room to read a single character. If the input contains more than one non-whitespace character at this point, the program will overflow the buffer. To read a single character and make it a one-character string, use

char T[2];
scanf("%c", T);
T[1] = 0;

scanf("%s", T) 不同,它读取任何字符,甚至是空格.要读取具有长度限制的字符串,请向 %s 规范添加限制.您永远不应该在 scanf 中使用无限的 %s,因为这将读取尽可能多的输入,无论有多少空间可以在内存中存储此输入.

Unlike scanf("%s", T), this reads any character, even whitespace. To read a string with a length limit, add a limit to the %s specification. You should never use an unlimited %s in scanf since this will read as much input as is available, regardless of how much room there is to store this input in memory.

char T[2];
scanf("%1s", T); // one less than the array size

这篇关于如果我使用“&amp;"会发生什么?在 scanf 函数中使用字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆