在C函数中传递指针参数

时间:2014-02-10 19:11:29

标签: c pointers

#include <stdio.h>

// this works
void print_stuff (void* buf) {
    printf ("passed arg as buf*: %s\n", buf);
}

/* This works */
void print_stuff_3 (char* buf) {
    printf ("passed arg as char*: %s\n", buf);
}

// this does not work
void print_stuff_2 (char** buf) {
    printf ("%s\n", *buf);
}

int main () {
    char s [] = "hi";

    printf ("s = %s\n", s); 

    // these work
    print_stuff (&s);
    print_stuff_3 (&s);

    // this results in a Segfault
    print_stuff_2(&s);
    return 0;
}

我对C中传递内容的方式感到有点困惑。我觉得&s应该是char**类型,但它的行为就像char*类型一样传递给函数时。为什么会出现这种情况?

特别是print_stuff_2段错误,而我认为print_stuff_3会出错。

编辑:澄清一下,我希望print_stuff(&s)print_stuff_3(&s)失败(虽然他们成功了),而print_stuff_2(&s)失败,而我觉得它应该成功。

3 个答案:

答案 0 :(得分:3)

你需要记住字符串不是C中的基本类型。它们是字符数组。因此

char s [] = "hi";

使s成为char *(就变量类型而言),即指向3个字符数组的第一个字符的指针(hi和{{ 1}})。

因此,为了传递指向字符串的指针,您使用NUL的内容,因为print_stuff_3的{​​{1}}参数正是如此(指向string,即指向第一个字符的指针。请使用printf()

进行调用

%s有效,因为指针是一个指针。它会在调用print_stuff_3(s)后转换为print_stuff指针,然后void * print_stuff会将其转换回printf()。请使用%s

进行调用

char *无法正常工作,因为您正在获取存储print_stuff(s)的地址。如果您使用print_stuff_2,那么您写的s是否可行。您将传递指针的地址,然后使用char *s = "hi";取消引用(以获取指针的值,即指向第一个字符的指针)。除了print_stuff_2(&s)之外,那么名称将是一个糟糕的选择,因为你将指向一个指向字符的指针。

复杂情况如下。实际上,您正在执行*buf,只有在您拥有

时才返回buf
&s

(参见How come an array's address is equal to its value in C?),但如果您有以下内容,则返回指针变量s存储在堆栈中的地址:

char s [] = "hi";

获取数组的地址并不真正有意义(因此计算第一个元素的地址)。如果要获取指针的地址,则需要使用s

答案 1 :(得分:0)

在C中,在大多数情况下,数组名称在传递给函数时会衰减指向其第一个元素。将s传递给函数print_stuff时,s会衰减指针h。无需通过&传递它。 &s是指向数组(char (*)[3])类型的指针,即它给出整个数组s的地址。

在函数调用中

print_stuff_3 (&s);  

你的编译器应警告你

[Warning] passing argument 1 of 'print_stuff_3' from incompatible pointer type [enabled by default]   
  

我觉得&s应该是char* *类型,但是当它传递给函数时,它的行为就好像它是char*类型一样。为什么会出现这种情况?

没有。你错了。 &amp; s属于char (*)[3]类型。

答案 2 :(得分:0)

void print_stuff (void* buf)&amp; void print_stuff_3 (char* buf)在这两个函数中,buf都是char *以地址为参数。哪个应该是print_stuff (s)&amp; print_stuff_3 (s)分别为s是char数组s的基址。因此,您不应该传递&s s的地址。

由于以下函数buf属于char **类型,如果您的声明为print_stuff_2(&s),则会预期地址为char *s = "hi"

void print_stuff_2 (char** buf) {
    printf ("%s\n", *buf);
}