无法理解 C 源代码,它不能在 GCC 中编译,但在 Visual C++ 中

Posted

技术标签:

【中文标题】无法理解 C 源代码,它不能在 GCC 中编译,但在 Visual C++ 中【英文标题】:Cannot understand C source and it does not compile in GCC, but in Visual C++ 【发布时间】:2011-01-31 11:04:15 【问题描述】:

在 GCC 中出现以下错误:

aes.c:在函数‘copy_block’中: aes.c:278:错误:需要左值作为增量操作数 aes.c:278: 错误:需要左值作为增量操作数

这是一段代码:

static void copy_block( void * d, void *s, uint_8t nn )

    while( nn-- )
        *((uint_8t*)d)++ = *((uint_8t*)s)++;

我试图将其更改为可编译的版本,但不幸的是,作为一名 Java 程序员,我不清楚这里到底发生了什么。

也许有人知道我可以如何更改它在 GCC 中可编译的源代码,或者有人知道这里详细发生了什么。对我来说,左手值的取消引用似乎很奇怪,但不知何故,它似​​乎在 Visual C++ 中完美运行。

这是一个小型遗留程序,我必须将其移植到 Linux 机器上。

提前感谢您的帮助。

【问题讨论】:

我想你想要uint8_t... 【参考方案1】:

试试这个:

#include <string.h>
static void copy_block( void * d, void *s, uint_8t nn ) 
  memcpy(d, s, (size_t)nn);

那里做的不好。

【讨论】:

那是 C++ ...帖子被标记为“C”,所以我会坚持使用 (size_t)nn 为什么不只是 #define copy_block memcpy 让它更有用? @Chris - 我认为首先编写 'copy_block' 而不是 'memcpy' 是有原因的 - 间接记录日志或其他内容。全局替换甚至比 #define 别名更好。 @sje397 呵呵 :) 但是您显然还需要将 #include 替换为 #include :p eek @246tNt - ta。回到我的盒子里:)【参考方案2】:

应该这样做:

static void copy_block(void *d, void *s, uint_8t nn)

    uint_8t *ud = (uint_8t *)d;
    uint_8t *us = (uint_8t *)s;

    while (nn--)
    
        *ud = *us;
        ++ud;
        ++us;
    

它也更具可读性。

【讨论】:

强制转换在 C 中是不必要且非惯用的 改用此代码!像在原始帖子中那样编写完全混淆的代码应该被定为犯罪!【参考方案3】:

这是一些看起来很毛茸茸的代码。看起来 *(pointer)++ 子表达式的优先级规则存在问题。 (Visual C++ 接受它介于奇迹和错误之间)它似乎只是一个(可怕的)memcpy 重新实现,所以我建议你使用标准版本:

memcpy(d, s, nn);

我建议在 Visual C++ 中进行快速特性测试,以确保代码的两个版本实际上执行相同的操作(正如它们看起来那样)。您可能在此处依赖编译器中的一些古怪的边缘情况。

【讨论】:

【参考方案4】:

问题是强制转换返回右值,但您正试图对强制转换返回的指针进行自动增量。试试这个:

uint8_t *da = d, *sa = s;
while(nn--) *da++ = *sa++;

另外两点:

nn 应该比 uint8_t 大很多,应该是 size_t。 进行该更改后,此函数被命名为 memcpy,并且可以在您的标准库中找到(可能更有效)(我相信在 string.h 中)。

【讨论】:

@Christoph - 一点也不。现在看起来不像我在 iPhone 上写的了。 :P【参考方案5】:

你可能搞砸了括号的位置。 您想增加指针,而不是取消引用的值。

static void copy_block( void * d, void *s, uint_8t nn )

    while( nn-- )
        *((uint_8t*)d++) = *((uint_8t*)s++);

作为额外提示,使用 memcpy ... 更快!

【讨论】:

后缀 ++ 比一元 * 具有更高的优先级,除非我错了。 不,后缀++ 的优先级更高,这意味着它比* 绑定得更紧密,这意味着您不需要为任何内容加上括号。代码仍然不起作用,因为您在右值上使用了自增运算符,这就是错误所述。 对于本应是一种语言的基本特征的东西争论不休。也许最好不要以容易被误读的方式编写代码。 K&R 和 70 年代的任何编程人员一样,编写代码是因为他们想节省源代码文件占用的硬盘空间。除非您的 Terrabyte HD 上更多字节的源代码是您的主要关注点,否则不要编写混淆代码。使用下面 detunized 发布的版本,它应该在性能方面完全等效。 @246tNt:您缺少-pedantic 标志:您的代码使用了非标准编译器扩展...【参考方案6】:

应该是:

static void copy_block( void * d, void *s, uint_8t nn )

    while( nn-- )
        (*((uint_8t*)d))++ = (*((uint_8t*)s))++;

【讨论】:

与原始代码相同的问题......没有工作希望。我很惊讶 visual-c++ 编译它。 ..

以上是关于无法理解 C 源代码,它不能在 GCC 中编译,但在 Visual C++ 中的主要内容,如果未能解决你的问题,请参考以下文章

MinGW gcc C 编译器可以工作,但 g++ 不能

如何在 AIX 中使用 GCC 编译器链接 *.so 文件

Matlab mex 无法构建,但 gcc 可以

gcc和g++的区别解析

Gcc 7.2 c++17 constexpr

代码可以用 VS 编译,但不能用 MinGW