返回一个带有指向数组成员的指针的结构体,返回值的指针不指向其数组成员

问题描述 投票:0回答:1

我正在编写一个词法分析器初始化函数,但是当我尝试设置 char* a = char* b 时,我得到 a != b??? 我尝试通过将 init 函数的 objdump 转换为 x86 asm 来追踪问题,但我对汇编非常陌生,所以我无法判断代码在做什么。

我尝试将 a = b 行移到 init 函数之外并且有效,但我更希望它可以保留在 init 函数内

这是C语言的代码

typedef struct {        
        char src[2048], *i; 
        FILE *fp;                       
}lexer_fp;

lexer_fp init_lexer_fp(FILE *fp) 
{                                       
        lexer_fp l;               
        l.fp = fp;                      
        fread(l.src, 1, 2048, fp);      
        l.i = l.src;                    
        return l;                   
}

void decompile(const char* filename)
{
        FILE * fp = fopen(filename, "r");
        lexer_fp lex = init_lexer_fp(fp);

        printf("i, src = %p, %p\n", lex.i, lex.src);

        fclose(fp);
}

printf 显示

lex.i
lex.src
指向 2 个不同的地址:

i, src = 0x7ffe20e51840, 0x7ffe20e520a0
。这个错误只是我的机器的问题吗?

c pointers struct
1个回答
0
投票

这个错误只是我的机器的问题吗?

不,这是您代码中的错误。

  • lexer_fp l;
    这个本地对象将有一个地址,比如说 0x1234。这意味着
    src
    也将具有地址 0x1234。并且您也指定
    i
    来指向该地址。
  • 然后你按值返回结构(真是个坏主意)。然后发生的事情是,调用代码中的结构体变量
    lex
    获得所有成员的 1 比 1 副本。
    src
    的内容将被复制,指针
    i
    fp
    将被复制并保留它们之前指向的确切地址。
  • 但是,
    lex
    src
    都没有分配在地址0x1234处。因此,
    i
    现在指向 la-la-land,取消引用它会导致未定义的行为。

C(和 C++)中的一般经验法则是“永远不要”通过值/简单赋值来复制结构,以防它们包含指针成员。在 C++ 中,您可以通过实现一个复制构造函数来解决这种情况,该构造函数对指针成员给予特别关注。 C 中没有这样的东西,所以 C 中的解决方案就是干脆不写这样的 bug。 相反,您可以通过引用传递结构,这不仅解决了问题,而且还带来了

巨大的

性能提升。在此过程中,实现实际的错误处理,这在处理文件时是强制性的。 typedef enum { LEX_OK, LEX_ERR_READ_FAILED, /* ... all errors that may happen in this lib */ } lex_result_t; lex_result_t lexer_fp_init (lexer_fp* lex, FILE* fp) { lex.fp = fp; size_t size_read = fread(lex.src, 1, 2048, fp); if(size_read != 2048) return LEX_ERR_READ_FAILED; lex.i = lex.src; return LEX_OK; } ... lex_result_t result; lexer_fp lex; result = lexer_fp_init(&lex, fp);

与您的问题无关,使用 
l

(L) 作为标识符的名称被广泛认为是不好的做法,因为它在许多字体上看起来像

1
(一)。一般来说,我们应该避免使用神秘的单字母变量名称,除非它们有意义(例如
i
是“迭代器”的事实标准,
n
表示项目的大小/数量等)。
    

© www.soinside.com 2019 - 2024. All rights reserved.