为什么不能在函数中修改结构的成员变量?

时间:2014-09-19 17:36:13

标签: c function struct parameters reference

我很好奇为什么在作为参数传递给函数时无法修改结构的变量。我知道参数是按值传递的,但是当传递一个struct变量时,你将它的引用作为值传递。

当然C不会在堆栈上创建结构的副本,因为传入的struct引用的值与将结构的指针传递给函数的值相同。

#include <stdio.h>
#include <stdlib.h>


typedef struct String {
    char* name;
    int x;
} String;

/* Func Protos */
void foo(String str);
void bar(String * str);
void banjo(String str);

int main() {
    String str = *(String *)malloc(sizeof(String));
    str.x = 5; /* x == 5 */
    foo(str); /* x == 5 still */
    printf("%d\n", str.x);
    banjo(str); /* x == 5 still */
    printf("%d\n", str.x);
    bar(&str); /* and of course, x = 0 now */
    printf("%d\n", str.x);
}

void foo(String str) {
    printf("%d\n", str); /* Same value as if we passed String * str */
    str.x = 0; 
}

void bar(String * str) {
    printf("%d\n", *str);
    str->x = 0;
}

void banjo(String str) {
    printf("%d\n", str);
    String * strptr = &str; /* This should be identical to passing String * str */
    strptr->x = 0;
}

生成此输出:

3415000
5
3415000
5
3415000
0

非常感谢任何帮助!

3 个答案:

答案 0 :(得分:4)

void banjo(String str) {
    printf("%d\n", str);
    String * strptr = &str; /* This should be identical to passing String * str */
    strptr->x = 0;
}

C是按值传递。 banjo函数中带有str参数的内容是main str对象的副本。

因此,您的banjo功能相当于:

void banjo(String str) {
    printf("%d\n", str);
    strptr.x = 0;  // useless, the object is discarded after function returns
}

顺便说一句printf("%d\n", str);无效。 d转换说明符需要int,但您传递的是结构值。该调用调用未定义的行为。如果要打印str对象使用的地址:

printf("%p\n", (void *p) &str);

答案 1 :(得分:0)

这一行:

String str = *(String *)malloc(sizeof(String));

为什么你会得到这种行为。将其更改为:

String *str = (String *)malloc(sizeof(String));

这将解决问题。

答案 2 :(得分:0)

声明

printf("%d\n", str);

不打印结构的地址,而是打印第一个元素的值 在结构内部。 并且由于结构中的第一个元素是指向char的指针,因此printf为 在控制台上给出了垃圾值。

试试这个例子:

#include<stdio.h>
struct a
{
   int b;
};

int main()
{
     struct a a1;
     a1.b = 10;  // try giving different value to a1.b
     printf("b = %u\n", a1.b);
     printf("a1 = %u\n", a1);
    return 0;
}

如果您认为正在打印结构的基地址,那么您实际上是在 打印结构内第一个元素的值。