我正在阅读K& R,并且在字符指针部分感到有些困惑。 K& R提供以下作为带指针的strcpy版本:
void strcpy(char *s, char *t) {
while ( (*s = *t) != '\0') {
s++;
t++;
}
}
这与使用指向单个字符的指针有什么不同?或者C只是相信我知道我在做什么,两种情况都使用指向角色的指针?只是当我有这些字符的数组时,它被\0
终止,而如果它只是一个字符,那么后续内存中的点可能是任何东西。这是对的吗?
答案 0 :(得分:4)
区分两者完全是你的责任。
在指向单个字符的指针的情况下,你可能会小心地将它作为char * const
,它不允许你递增指针或以其他方式改变它指向的内容并走到某处和未定义的行为,但您仍然可以修改它指向的值。
C是非常低的水平,非常“bare骨头”#34;语言。使用指针时,你必须要负起责任。当然,这适用于char *
以及任何其他"数组" - 如果不是null终止,你应该通过所有方式传递数组的长度并将其用作指南。
答案 1 :(得分:2)
作为参数传递给函数的数组被隐式转换为指向其第一个元素的指针。因此,指针指向单个标量对象还是指向数组的第一个对象没有区别。指针不具备这样的信息。
对于名称从str
开始的标准字符串函数,假设它们处理包含以零结尾的数据的字符数组的字符串。
所以实际上你可以犯一个错误,并将一个指向单个字符对象的指针传递给字符串函数。但在这种情况下,程序行为将是未定义的。
另一方面,如果要完全遵循帖子的标题,则指向字符数组的指针与指向单个字符的指针不同。
例如,请考虑以下声明
char *pc = "Hello";
char ( *ps )[6] = &"Hello";
正如您所见pc
和ps
其中ps
是指向字符数组的指针具有不同的声明。:)如果您取消引用指针,您还可以看到差异。例如
printf( "%zu\n", sizeof( *pc ) );
printf( "%zu\n", sizeof( *ps ) );
答案 2 :(得分:2)
你基本上是正确的。它与指向单个字符的指针没什么区别。该函数不知道传递单个字符(坏)和传递字符串(好)之间的区别。如果您碰巧传递了单个字符的地址(具有非零值),则此函数的行为将是未定义的。在这种情况下,C不是typesafe。
答案 3 :(得分:1)
这与使用指向单个字符的指针有什么不同?
不同之处在于,当您使用指向单个字符的指针时,您不应该增加该指针,而应该只增加一次,条件是您不能取消引用它。在指向字符串的单个字符的情况下,指针可以递增,直到超过最后一个元素。
如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出; [...]
实际上,指向单个元素的指针表现为指向一个元素数组的指针。
char c = 'A';
char *p = &c; // Pointer to char
类似于(除了c
在这种情况下是一个数组)
char c[1] = {'A'};
char *p = c; // Pointer to the first element of array c.
或者C只是相信我知道自己在做什么,两种情况都使用指向角色的指针?
是。你应该注意指针应该指向一个数组/字符串对象的元素,或者指向它的一个元素,在后一种情况下不提供解引用。
答案 4 :(得分:-1)
应该使用指向未知字符数组的指针。这是每个人都应该做的,但AFAIK没有人这样做:
void str_cpy(char (*s)[], char (*t)[]) {{
char *str_cpy[2] = { *s, *t }, *s = *str_cpy, *t = str_cpy[1];
{
void str_cpy(char (*s)[], char (*t)[]);
while ( (*s = *t) != '\0') s++, t++;
}
}}
请注意,禁止将指针递增到未知大小的数组,这里也不需要,因此需要更改功能代码(如上所述)。
然后您可以传递这样的字符串:
char str[20], str1[20];
strcpy(&str, &str1);
通过这种方式,您可以诊断意外地将指针传递给单个字符:
char singleChar = 'H';
strcpy(&singleChar, &singleChar); //warning
生命example。
但问题是,使用char *
变量是从任何" char"数组中访问每个char
的最实用的方法。因为你可以直接递增这样一个变量,使它引用下一个数组元素(你不能使用指向数组的指针 - 递增这样会使它引用内存中的下一个数组而不是下一个数组。数组指出)。另外,使用指向数组的指针的语法更复杂。