我正在编写一个词法分析器初始化函数,但是当我尝试设置 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
。这个错误只是我的机器的问题吗?
这个错误只是我的机器的问题吗?
不,这是您代码中的错误。
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
表示项目的大小/数量等)。