【问题标题】:Macro returning a pointer, Seg fault宏返回指针,Seg 错误
【发布时间】:2017-12-01 07:29:03
【问题描述】:

所以我有这段代码可以正常工作

#include <stdio.h>
#define B(X) &X
struct abc{
    char temp[2];
};

void print(char *string)
{
    printf("%s\n", string);
}
int main()
{
    struct abc *pAbc = malloc(sizeof(struct abc));
    pAbc->temp[0] = 'a';
    pAbc->temp[1] = '\0';
    print(pAbc->temp);
    free(pAbc);
    return 0;
}

但这不起作用

#include <stdio.h>
#define B(X) &X
struct abc{
    char temp[2];
};

void print(char **string)
{
    printf("%s\n", *string);
}
int main()
{
    struct abc *pAbc = malloc(sizeof(struct abc));
    pAbc->temp[0] = 'a';
    pAbc->temp[1] = '\0';
    print(B(pAbc->temp));
    free(pAbc);
    return 0;
}

据我了解,宏定义应该返回变量的地址。

这个函数与 int 配合得很好。

编辑:

对不起,我忘了提到我想做的事情,我想传递一个指向函数指针的指针,因为我只想为一些编译路径这样做,我想设置一个选项,比如

if #defined WIN32
print(B(varible))
elif #defined GCC
print(varible)

【问题讨论】:

  • @RingØ 我不确定这是不是骗子,你为什么这么说?
  • 这是一个可能的骗局,因为问题的基本原因是x&amp;x 返回相同的地址。阅读提到的问答将避免错误。如果您不同意,请不要投票。
  • pAbc-&gt;temp&amp;pAbc-&gt;temp 不是一回事,是否通过宏完成无关紧要。

标签: c arrays string macros


【解决方案1】:

您编译时是否启用了警告?你应该得到:

prog.c:3:14: warning: passing argument 1 of 'print' from incompatible pointer type [-Wincompatible-pointer-types]
 #define B(X) &X
              ^~
prog.c:17:11: note: in expansion of macro 'B'
     print(B(pAbc->temp));
           ^
prog.c:8:19: note: expected 'char **' but argument is of type 'char (*)[2]'
 void print(char **string)
            ~~~~~~~^~~~~~

您的打印函数中不需要双指针,因此只需将其修改回使用单指针,然后更改:

#define B(X) &X

到这里:

#define B(X) X

编辑:

你想做的事不用宏就可以轻松实现,像这样:

char* temp= pAbc->temp;
print(&temp);

【讨论】:

  • 我想要做的是为一些我想要创建宏的编译路径传递一个双指针。编辑了问题。
【解决方案2】:

你可以试试

printf("%p %p",pAbc->temp,&pAbc->temp);

看到它们都评估为相同的地址,在 print 内,您错误地期望双指针导致无效的内存访问

【讨论】:

  • 哦!那么我将如何创建一个创建双指针的宏呢?
【解决方案3】:

问题在于&amp;pAbc-&gt;temp 的类型为char (*)[2],而不是char **。实际上,您应该收到关于不兼容指针类型的编译错误(或至少是警告)(您是否启用了警告?)

如果你想获得char **,你可以这样做:

char *tmp = pAbc->temp;

然后使用&amp;tmp 作为print 的参数。

但是,您为什么需要额外的间接级别?通常仅当您想从被调用函数中修改指针时才需要它,在这种情况下这是不可能的(这基本上意味着更改数组的地址)。我提供的解决方案会起作用,但在这种情况下,您最终会更改 tmp,这值得怀疑。

【讨论】:

    【解决方案4】:

    您向函数发送了错误的参数。这会导致未定义的行为。正确的方法,在结构体中发送数组地址的地址是使用临时变量。

    #include <stdio.h>
    
    struct foo {
      char bar[2];
    };
    
    static void print(char **string) { printf("%s\n", *string); }
    
    int main() {
      struct foo a = {.bar = "a"};
      char *p = a.bar;
      print(&p);
    }
    

    【讨论】:

    • "您向函数发送了错误的参数,这是未定义的行为。" - 澄清一下,一般来说,是否将char 发送到期望int UB 的函数?我猜不是。
    • @babon 我不想这么说。
    • :) 是的,我明白这一点。只是在一般意义上指出这句话对某人可能意味着什么,仅此而已。
    猜你喜欢
    • 1970-01-01
    • 2020-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-22
    相关资源
    最近更新 更多