简体   繁体   English

在C函数中传递指针参数

[英]Passing pointer arguments in C functions

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

I am a bit confused about the way things are passed around in C. I feel like &s should be of type char** , but it behaves as if it is of type char* when passed to a function. 我对C语言中的事物传递方式有些困惑。我觉得&s应该是char**类型,但是在传递给函数时,它的行为就像是char*类型。 Why does this behaviour happen? 为什么会发生这种现象?

In particular, print_stuff_2 segfaults, whereas I thought that print_stuff_3 would give an error. 特别是print_stuff_2 segfaults,而我认为print_stuff_3会给出错误。

EDIT: To clarify, I expected print_stuff(&s) and print_stuff_3(&s) to fail (while they succeed), while print_stuff_2(&s) fails, whereas I feel it should succeed. 编辑:澄清一下,我期望print_stuff(&s)print_stuff_3(&s)失败(虽然它们成功了),而print_stuff_2(&s)失败了,但是我认为它应该成功。

You need to remember that strings are not fundamental types in C. They are arrays of characters. 您需要记住,字符串不是C中的基本类型。它们是字符数组。 Therefore 因此

char s [] = "hi";

makes s a char * (in terms of variable type), ie a pointer to the first character of a 3 character array ( h , i and NUL ). 使schar * (就变量类型而言),即指向3个字符数组的第一个字符( hiNUL )的指针。

So in order to pass a pointer to the string, you what to use your print_stuff_3 , as printf() 's %s argument takes exactly that (a pointer to the string, ie a pointer to the first character). 因此,为了传递一个指向字符串的指针,您需要使用print_stuff_3 ,因为printf()%s参数采用了该参数(指向字符串的指针,即指向第一个字符的指针)。 Call this with print_stuff_3(s) . 调用print_stuff_3(s)

print_stuff works because a pointer is a pointer. print_stuff之所以有效,是因为指针是指针。 It will be translated to a void * pointer on calling print_stuff , then printf() 's %s will convert it back to a char * . 它将在调用print_stuff转换为void *指针,然后printf()%s会将其转换回char * Call this with print_stuff(s) . print_stuff(s)调用它。

print_stuff_2 doesn't work because you are taking the address of where s is stored. print_stuff_2不起作用,因为您要使用存储s的地址。 Had you written char *s = "hi"; 你写过char *s = "hi";char *s = "hi"; that would work if you used print_stuff_2(&s) . 如果您使用print_stuff_2(&s) ,它将起作用。 You'd pass the address of the pointer, then dereference that (to get the value of the pointer, ie the pointer to the first character) in by using *buf . 您将传递指针的地址,然后使用*buf取消引用该指针(以获取指针的值,即指向第一个字符的指针)。 Except buf then would be a poor choice of name, as you would be passing a pointer to a pointer to characters. 除了buf之外,名称的选择很差,因为您要传递一个指向字符的指针。

The complication is as follows. 并发症如下。 As it is, you are doing &s which just returns s when you have 正因为如此,你在做&s刚刚返回s当你有

char s [] = "hi";

(see How come an array's address is equal to its value in C? ), but returns the address at which the pointer variable s is stored on the stack if you have: (请参阅数组的地址如何等于其在C中的值? ),但如果有以下情况,则返回将指针变量s存储在堆栈上的地址:

char *s = "hi";

Taking the address of an array doesn't really make sense (so evaluates to the address of the first element). 取数组的地址实际上没有任何意义(因此求值第一个元素的地址)。 You need to use char *s = "hi"; 您需要使用char *s = "hi"; if you want to take the address of the pointer. 如果要获取指针的地址。

In C, array names are decays to pointer to its first element when passed to a function in most cases. 在C语言中,大多数情况下,数组名称在传递给函数时会衰减指向其第一个元素的指针。 When passing s to the function print_stuff , s decays to pointer to h . s传递给函数print_stuffs衰减为指向h指针。 No need to pass it with & . 无需使用&传递它。 &s is of pointer to array ( char (*)[3] ) type, ie, it is giving the address of the entire array s . &s指向数组( char (*)[3] )类型的指针,即,它给出了整个数组s的地址。

In function call 在函数调用中

print_stuff_3 (&s);  

your compiler should warn you 您的编译器应警告您

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

I feel like &s should be of type char* *, but it behaves as if it is of type char* when passed to a function. 我觉得&s应该是char* *类型,但是当传递给函数时,它的行为就像是char*类型。 Why does this behavior happen? 为什么会发生这种现象?

No. You thought wrong. 不,你想错了。 &s is of type char (*)[3] . &s的类型为char (*)[3]

void print_stuff (void* buf) & void print_stuff_3 (char* buf) In both functions, buf is of char * taking address as argument. void print_stuff (void* buf)void print_stuff_3 (char* buf)在两个函数中, buf都是char *以address作为参数。 Which should be print_stuff (s) & print_stuff_3 (s) respectively as s is the base address of char array s . print_stuff (s)print_stuff_3 (s)分别为s是字符数组的基地址s So you shouldn't pass &s which is address of s . 因此,您不应传递&s这是s地址。

As the below function buf is of type char ** , it will expect address of address like print_stuff_2(&s) provided your declaration is char *s = "hi" , 由于以下函数buf的类型为char ** ,因此如果您的声明为char *s = "hi" ,它将期望使用类似于print_stuff_2(&s)地址的地址,

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM