c - 递增数组指针

时间:2016-01-24 11:37:37

标签: 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++ = '2';
}

int main(int argc, char **argv)
{
    char tmp[5];
    test(tmp);
    printf("%s", tmp);
    return 0;
}

仅打印34。当我在函数test2中调试此代码时,在调用test2之后,tmp的指针增加1但返回函数testtmp的指针返回其初始值。
如果我只是将所有代码放在这样的单个函数中,它就可以工作:

void test(char *tmp)
{
    *tmp++ = '1';
    *tmp++ = '2';
    *tmp++ = '3';
    *tmp++ = '4';
    *tmp = 0;
}

最后一行的*tmp = 0是做什么的。我从其他一些代码中复制了它。没有它,数组的末尾会有一些垃圾。

5 个答案:

答案 0 :(得分:4)

在函数test2中,按指针传递意味着您可以修改tmp指向的内容,但test2 不会修改指针本身。< / p>

void test2(char *tmp)
{
    *tmp++ = '1';
    *tmp++ = '2';
}

所以在调用函数test中,在调用test2后,指针不会像你期望的那样向前移动2个位置,而tmp保持不变(指向数组的第一个值)。那么实际发生的是test2为前两个元素分配12,然后test3和{{1}覆盖这两个值}。

4
  

最后一行的* tmp = 0也是如此。

该字符串终止符。

答案 1 :(得分:2)

增加&#39; tmp&#39;在test2()中没有增加&t; tmp&#39;在test()中。在test2()调用返回后,&#39; 1&#39;和&#39; 2&#39; test2编写的内容被&#39; 3&#39;和&#39; 4&#39;。

零是&#39; \ 0&#39; c-style&#39; string&#39;终止子。

答案 2 :(得分:1)

函数参数是其局部变量。参数通过值传递给函数,这意味着传递参数的副本。

因此,在函数test2中,使用了函数tmp的指针test的副本。对象副本的任何更改都不会影响对象本身。

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";

这是字符串文字"Hello"在表达式中用作初始值设定项。包含终止零'\0'的字符串文字类型char[6]被隐式转换为指向其第一个字符'H'的指针。

在C ++中,字符串文字具有常量字符数组的类型。因此C ++中的字符串文字"Hello"具有类型const char[6]

所以在C ++中你必须写

const char *s = "Hello";

但在这两种语言中,字符串文字是不可变的。

答案 3 :(得分:1)

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;
}

这里test2将更改/递增的指针返回给调用者,tess()将接收更新的char。由于你在teh end添加了0或nul字节,所以你需要一个至少包含5个元素的数组。

以上代码应该可以正常使用。

答案 4 :(得分:0)

正常情况下,如果你在1个函数中写入全部,你得到1234,但是如果你写2个函数总是传递相同的指针,第二个函数会覆盖第一个已经完成的函数。

select e.empid,
       coalesce(max(case when '2016-01-24' between v.startdate and v.enddate 
                         then leave_type end),
                'available') as [2016-01-14],
       coalesce(max(case when '2016-01-25' between v.startdate and v.enddate 
                         then leave_type end),
                'available') as [2016-01-15],
       . . .
from emp e left join
     from vacation v
     on e.empid = v.empid
group by e.empid;

现在我想你可以看到错误。