什么是 C 中指向 'array of characters' 的指针?
What is a pointer to an 'array of characters' in C?
int check_authentication(char *password)
// 1
{
int auth_flag = 0;
char password_buffer[16];
strcpy(password_buffer, password); // 2
if(strcmp(password_buffer, "brillig") == 0)
auth_flag = 1;
if(strcmp(password_buffer, "outgrabe") == 0)
auth_flag = 1;
return auth_flag;
}
check_authentication(argv[1]) // Passing a 'Command Line argument'
// ( which is a string in this example) to the check_authentication function.
我有两个问题。上面标记为 1 和 2 的行,
该函数需要一个字符指针作为参数。但是我们传递了一个 "string" 即一个字符数组作为参数。怎么样?????
指针"password"(指向一个字符)持有的地址被复制到"password_buffer"数组。对我来说完全是无稽之谈 。请解释一下。
您正在传递指向字符串中第一个字符的字符指针。您实际上并没有传递整个字符串。
strcpy
函数读取这个指针指向的字符,然后从下一个内存位置继续读取连续的字符,直到遇到空终止符。
strcpy
的第一个参数和 strcmp
的两个参数以相同的方式工作。
字符串实际上只是以空字节结束的字符数组[=10=]
。数组是字符串本身,但是 char 指针是数组第 0 个位置的内存位置。
strcpy
从 char 指针指向的内存位置开始读取字符,直到遇到空终止字符。
数组实际上并不是这样传递的。传递的是指向数组第一个元素的指针。 C 中的字符串实际上是一个以 NUL
结尾的字符数组,它是指向传递的第一个元素的指针。
您真的应该仔细阅读 strcpy
联机帮助页 http://linux.die.net/man/3/strcpy。没有地址被复制到那里。该函数所做的就是获取一个字符串(字符数组)password
指针指向并将在该地址找到的所有字符复制到 NUL
到 password_buffer
指针指向的地址.
The function expects a character pointer as an argument. But we pass a "string" i,e an array of characters as an argument. How ?????
除非它是 sizeof
或一元 &
运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字,表达式 类型 "N-element array of T
" 将被转换 ("decay") 为类型 "pointer to T
" 的表达式,表达式的值将是数组第一个元素的地址。
当你打电话时
strcpy(password_buffer, password);
表达式 password_buffer
的类型为“char
的 16 元素数组”;因为表达式不是 sizeof
或一元 &
运算符的操作数,所以表达式被转换 ("decays") 为类型 "pointer to char
",并且表达式的值是第一个元素的地址。这个指针值是传递给 strcpy
的值。
简而言之,任何时候将数组表达式传递给函数时,函数都会收到一个指针值。在函数参数声明的上下文中,T a[]
和 T a[N]
将被解释为 T *a
。
信不信由你,Ritchie 确实有这样设计语言的理由;有关详细信息,请参阅 this paper(查找标题为 "Embryonic C" 的部分)。
The address held by the pointer "password" (that points to a character) is copied to the "password_buffer" array. It makes no sense to me . Pls explain.
事实并非如此;正在发生的事情是 strcpy
正在复制缓冲区的 内容 ,从 password
给定的地址开始到 password_buffer
。想象一下下面的内存映射:
Item Address 0x00 0x01 0x02 0x03
---- ------- ---- ---- ---- ----
"foo" 0x7fffc7cf4b22 'f' 'o' 'o' 0
argv[1] 0x7fffc7cf2670 0x00 0x00 0x7f 0xff
0xc7 0xcf 0x4b 0x22
password 0x7ffffdbe1878 0x00 0x00 0x7f 0xff
0xfd 0xbe 0x2v 0x22
password_buffer 0x7ffffdbe1880 0x?? 0x?? 0x?? 0x??
0x?? 0x?? 0x?? 0x??
0x?? 0x?? 0x?? 0x??
0x?? 0x?? 0x?? 0x??
其中 0x??
表示 unknown/indeterminate 字节值。
命令行参数字符串 "foo" 存储在地址 0x7fffc7cf4b22
。请注意,在 C 中,string 只是一个以 0 值字节结尾的字符值序列。字符串存储为 char
的数组(在 C++ 中为 const char
),但并非所有 char
的数组都包含字符串。
argv[1]
表达式计算第一个命令行参数的地址,即字符串 "foo"
的地址,即 0x7fffc7cf4b22
。此值传递给 check_authentication
函数并存储到 password
参数。注意 argv[1]
和 password
在内存中是不同的项(它们有不同的地址),但都包含相同的 value (字符串的地址 "foo"
).
password_buffer
数组从地址 0x7ffffdbe1880
开始。由于它没有声明 static
并且没有显式初始化程序,因此数组的内容是 不确定的。
strcpy
函数将从地址 0x7fffc7cf4b22
开始的字符串内容复制到从地址 0x7ffffdbe1880
开始的缓冲区中,直到它看到该值为 0 的字节。在调用 strcpy
之后,我们的内存是这样的:
Item Address 0x00 0x01 0x02 0x03
---- ------- ---- ---- ---- ----
"foo" 0x7fffc7cf4b22 'f' 'o' 'o' 0
argv[1] 0x7fffc7cf2670 0x00 0x00 0x7f 0xff
0xc7 0xcf 0x4b 0x22
password 0x7ffffdbe1878 0x00 0x00 0x7f 0xff
0xfd 0xbe 0x2v 0x22
password_buffer 0x7ffffdbe1880 'f' 'o' 'o' 0
0x?? 0x?? 0x?? 0x??
0x?? 0x?? 0x?? 0x??
0x?? 0x?? 0x?? 0x??
int check_authentication(char *password)
// 1
{
int auth_flag = 0;
char password_buffer[16];
strcpy(password_buffer, password); // 2
if(strcmp(password_buffer, "brillig") == 0)
auth_flag = 1;
if(strcmp(password_buffer, "outgrabe") == 0)
auth_flag = 1;
return auth_flag;
}
check_authentication(argv[1]) // Passing a 'Command Line argument'
// ( which is a string in this example) to the check_authentication function.
我有两个问题。上面标记为 1 和 2 的行,
该函数需要一个字符指针作为参数。但是我们传递了一个 "string" 即一个字符数组作为参数。怎么样?????
指针"password"(指向一个字符)持有的地址被复制到"password_buffer"数组。对我来说完全是无稽之谈 。请解释一下。
您正在传递指向字符串中第一个字符的字符指针。您实际上并没有传递整个字符串。
strcpy
函数读取这个指针指向的字符,然后从下一个内存位置继续读取连续的字符,直到遇到空终止符。
strcpy
的第一个参数和 strcmp
的两个参数以相同的方式工作。
字符串实际上只是以空字节结束的字符数组[=10=]
。数组是字符串本身,但是 char 指针是数组第 0 个位置的内存位置。
strcpy
从 char 指针指向的内存位置开始读取字符,直到遇到空终止字符。
数组实际上并不是这样传递的。传递的是指向数组第一个元素的指针。 C 中的字符串实际上是一个以
NUL
结尾的字符数组,它是指向传递的第一个元素的指针。您真的应该仔细阅读
strcpy
联机帮助页 http://linux.die.net/man/3/strcpy。没有地址被复制到那里。该函数所做的就是获取一个字符串(字符数组)password
指针指向并将在该地址找到的所有字符复制到NUL
到password_buffer
指针指向的地址.
The function expects a character pointer as an argument. But we pass a "string" i,e an array of characters as an argument. How ?????
除非它是 sizeof
或一元 &
运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字,表达式 类型 "N-element array of T
" 将被转换 ("decay") 为类型 "pointer to T
" 的表达式,表达式的值将是数组第一个元素的地址。
当你打电话时
strcpy(password_buffer, password);
表达式 password_buffer
的类型为“char
的 16 元素数组”;因为表达式不是 sizeof
或一元 &
运算符的操作数,所以表达式被转换 ("decays") 为类型 "pointer to char
",并且表达式的值是第一个元素的地址。这个指针值是传递给 strcpy
的值。
简而言之,任何时候将数组表达式传递给函数时,函数都会收到一个指针值。在函数参数声明的上下文中,T a[]
和 T a[N]
将被解释为 T *a
。
信不信由你,Ritchie 确实有这样设计语言的理由;有关详细信息,请参阅 this paper(查找标题为 "Embryonic C" 的部分)。
The address held by the pointer "password" (that points to a character) is copied to the "password_buffer" array. It makes no sense to me . Pls explain.
事实并非如此;正在发生的事情是 strcpy
正在复制缓冲区的 内容 ,从 password
给定的地址开始到 password_buffer
。想象一下下面的内存映射:
Item Address 0x00 0x01 0x02 0x03
---- ------- ---- ---- ---- ----
"foo" 0x7fffc7cf4b22 'f' 'o' 'o' 0
argv[1] 0x7fffc7cf2670 0x00 0x00 0x7f 0xff
0xc7 0xcf 0x4b 0x22
password 0x7ffffdbe1878 0x00 0x00 0x7f 0xff
0xfd 0xbe 0x2v 0x22
password_buffer 0x7ffffdbe1880 0x?? 0x?? 0x?? 0x??
0x?? 0x?? 0x?? 0x??
0x?? 0x?? 0x?? 0x??
0x?? 0x?? 0x?? 0x??
其中 0x??
表示 unknown/indeterminate 字节值。
命令行参数字符串 "foo" 存储在地址 0x7fffc7cf4b22
。请注意,在 C 中,string 只是一个以 0 值字节结尾的字符值序列。字符串存储为 char
的数组(在 C++ 中为 const char
),但并非所有 char
的数组都包含字符串。
argv[1]
表达式计算第一个命令行参数的地址,即字符串 "foo"
的地址,即 0x7fffc7cf4b22
。此值传递给 check_authentication
函数并存储到 password
参数。注意 argv[1]
和 password
在内存中是不同的项(它们有不同的地址),但都包含相同的 value (字符串的地址 "foo"
).
password_buffer
数组从地址 0x7ffffdbe1880
开始。由于它没有声明 static
并且没有显式初始化程序,因此数组的内容是 不确定的。
strcpy
函数将从地址 0x7fffc7cf4b22
开始的字符串内容复制到从地址 0x7ffffdbe1880
开始的缓冲区中,直到它看到该值为 0 的字节。在调用 strcpy
之后,我们的内存是这样的:
Item Address 0x00 0x01 0x02 0x03
---- ------- ---- ---- ---- ----
"foo" 0x7fffc7cf4b22 'f' 'o' 'o' 0
argv[1] 0x7fffc7cf2670 0x00 0x00 0x7f 0xff
0xc7 0xcf 0x4b 0x22
password 0x7ffffdbe1878 0x00 0x00 0x7f 0xff
0xfd 0xbe 0x2v 0x22
password_buffer 0x7ffffdbe1880 'f' 'o' 'o' 0
0x?? 0x?? 0x?? 0x??
0x?? 0x?? 0x?? 0x??
0x?? 0x?? 0x?? 0x??