c-递增数组指针
有人能给我解释一下为什么这样不行吗。我是java开发人员,不熟悉c/c++c-递增数组指针,c,arrays,pointers,C,Arrays,Pointers,有人能给我解释一下为什么这样不行吗。我是java开发人员,不熟悉c/c++ 据我所知,数组的指针实际上是数组第一个元素的指针,对吗 void test(char *tmp) { test2(tmp); //*tmp++ = '1'; //*tmp++ = '2'; *tmp++ = '3'; *tmp++ = '4'; *tmp = 0; } void test2(char *tmp) { *tmp++ = '1'; *tmp++
据我所知,数组的指针实际上是数组第一个元素的指针,对吗
void test(char *tmp)
{
test2(tmp);
//*tmp++ = '1';
//*tmp++ = '2';
*tmp++ = '3';
*tmp++ = '4';
*tmp = 0;
}
void test2(char *tmp)
{
*tmp++ = '1';
*tmp++ = '2';
}
int main(int argc, char **argv)
{
char tmp[5];
test(tmp);
printf("%s", tmp);
return 0;
}
仅打印34
。当我在函数test2
中调试此代码时,tmp
的指针增加1,但在调用test2后返回函数test
中,tmp
的指针返回其初始值。如果我将所有代码放在一个函数中,就像这样,它可以工作:
void test(char *tmp)
{
*tmp++ = '1';
*tmp++ = '2';
*tmp++ = '3';
*tmp++ = '4';
*tmp = 0;
}
最后一行上的
*tmp=0
还有什么作用。我从其他代码中复制了它。如果没有它,数组的末尾会有一些垃圾。增加test2()中的“tmp”不会增加test()中的“tmp”。在test2()调用返回后,test2编写的“1”和“2”将被“3”和“4”覆盖
零是“\0”c样式的“字符串”终止符。在函数
test2
中,通过指针意味着您可以修改tmp指向的内容,但test2
不会修改指针本身
void test2(char *tmp)
{
*tmp++ = '1';
*tmp++ = '2';
}
因此,在调用函数test
中,调用test2
后,指针不会像预期的那样向前移动2个位置,而是tmp
保持不变(指向数组的第一个值)。因此,实际发生的是test2
为前两个元素分配1
和2
,然后test
用3
和4
覆盖这两个值
void test(char *tmp)
{
test2(tmp);
*tmp++ = '3';
*tmp++ = '4';
*tmp = 0;
}
最后一行上的*tmp=0也是做什么的
这是字符串终止符。如果在1个函数中写入所有函数,则得到1234,这是正常的,但如果写入2个函数时始终传递相同的指针,则第二个函数将覆盖第一个函数已经完成的操作
test:
tmp -> Point to [100]
call test2 giving [100] as parameter
write 3 in [100]
increment pointer from [100] to [101]
write 4 in [101]
increment pointer from [101] to [102]
test2:
tmp -> Point to [100]
write 1 in [100]
increment pointer from [100] to [101]
write 2 in [101]
increment pointer from [101] to [102]
现在我想您可以看到错误。函数参数是它的局部变量。参数通过值传递给函数,这意味着传递参数的副本 因此,在函数
test2
中,使用了函数test
的指针tmp
的副本。对象副本的任何更改都不会影响对象本身
test2的调用可以想象如下方式
void test(char *tmp)
{
// test2(tmp);
char *new_ptr = tmp;
test2( new_ptr );
// ...
}
void test2(/*char *tmp*/)
{
char *tmp = new_ptr;
*tmp++ = '1';
*tmp++ = '2';
}
如果您将test2
的参数声明为指针的引用,那么在这种情况下,指针本身可以更改。比如说
void test(char *tmp)
{
test2( &tmp );
// ^^^^
//*tmp++ = '1';
//*tmp++ = '2';
*tmp++ = '3';
*tmp++ = '4';
*tmp = 0;
}
void test2(char **tmp)
// ^^^^^^^^^^
{
*( *tmp )++ = '1';
*( *tmp )++ = '2';
}
对于数组,表达式中使用的数组(很少有例外,例如在运算符sizeof
中使用数组)被隐式转换为指向其第一个元素的指针
例如,如果您有一个类型为T
T a[N];
那么下面的声明
T *p = a;
有效,指针由数组a
的第一个元素的地址初始化
另一个例子
char *s = "Hello";
下面是字符串literal“Hello”
在表达式中用作初始值设定项。包含终止零'\0'
的字符串文本的类型为char[6]
,隐式转换为指向其第一个字符'H'
的指针
<>在C++字符串中有固定字符数组的类型。因此,C++中的字符串文字<代码>“hello”<代码>具有类型<代码> const char(6)< /C> > /P>
在C++中,你必须写< /P>
const char *s = "Hello";
但在这两种语言中,字符串文字是不可变的。0是nul终止符,字符串以0或nul字节结尾,因此printf()之类的函数知道字符串的结尾,因为-一段字符串有多长 由于您正在将指针传递给test2(),test2()正在递增指针-但实际上并没有将更改/递增的指针传递回调用函数…就test()而言,指针没有更改,因此后续的更改将覆盖以前的更改
#include <stdio.h>
#include <stdlib.h>
char *test2(char *tmp)
{
*tmp++ = '1';
*tmp++ = '2';
return tmp;
}
void test(char *tmp)
{
tmp = test2(tmp);
//*tmp++ = '1';
//*tmp++ = '2';
*tmp++ = '3';
*tmp++ = '4';
*tmp = 0;
}
int main(int argc, char **argv)
{
char tmp[5];
test(tmp);
printf("%s", tmp);
return 0;
}
#包括
#包括
char*test2(char*tmp)
{
*tmp++='1';
*tmp++='2';
返回tmp;
}
无效测试(字符*tmp)
{
tmp=test2(tmp);
//*tmp++='1';
//*tmp++='2';
*tmp++='3';
*tmp++='4';
*tmp=0;
}
int main(int argc,字符**argv)
{
char-tmp[5];
试验(tmp);
printf(“%s”,tmp);
返回0;
}
这里test2将更改/增加的指针返回给调用者,tess()将接收更新的字符。由于要在末尾添加0或nul字节,因此这里需要至少包含5个元素的数组
上面的代码应该可以正常工作。1。字符串以null结尾(因此
*tmp=0
)。2.通过使用tmp[0]=
等方法使代码可读。Ed Heal可以工作,这是我尝试的第一件事,但我不希望test
依赖于test2
。例如,如果我在test2
3次中增加tmp,我希望在测试中从前面继续。这可能吗?@dasblinkenlight fixed如果我有4个元素,我是否需要创建大小为5的数组?@pedja是的,如果字符串中有四个字母,则需要一个包含五个char
s的数组来容纳空终止符。那么,如果不显式指定数组索引,我怎么做呢?例如tmp[0]
,tmp[1]
等。一种方法是从test2()返回指针:'char*test2(char*tmp)'…'返回tmp;'从temp中将其命名为:“tmp=test2(tmp);”好的,我现在明白了,但是我怎样才能使它像这样工作,而不使用tmp[0]
,tmp[1]
等等