小编Mat*_*att的帖子

为什么gcc会创建冗余汇编代码?

我想研究一下如何将某些C/C++特性转换为汇编,并创建了以下文件:

struct foo {
    int x;
    char y[0];
};

char *bar(struct foo *f)
{
    return f->y;
}
Run Code Online (Sandbox Code Playgroud)

然后我编译了这个gcc -S(并且也试过g++ -S)但是当我查看汇编代码时,我很失望地发现bar函数中的一个微不足道的冗余,我认为gcc应该能够优化掉:

_bar:
Leh_func_begin1:
        pushq   %rbp
Ltmp0:
        movq    %rsp, %rbp
Ltmp1:
        movq    %rdi, -8(%rbp)
        movq    -8(%rbp), %rax
        movabsq $4, %rcx
        addq    %rcx, %rax
        movq    %rax, -24(%rbp)
        movq    -24(%rbp), %rax
        movq    %rax, -16(%rbp)
        movq    -16(%rbp), %rax
        popq    %rbp
        ret
Leh_func_end1:
Run Code Online (Sandbox Code Playgroud)

除其他外,线条

        movq    %rax, -24(%rbp)
        movq    -24(%rbp), %rax
        movq    %rax, -16(%rbp)
        movq    -16(%rbp), %rax
Run Code Online (Sandbox Code Playgroud)

似乎毫无意义多余.是否有任何理由gcc(可能还有其他编译器)不能/不优化它?

c compiler-construction optimization assembly gcc

5
推荐指数
2
解决办法
651
查看次数

在大多数现代64位处理器上,`mulq`的速度是否取决于操作数?

在大多数现代64位处理器(例如Intel Core 2 Duo或Intel i7系列)上,x86_64命令mulq及其变体的速度是否取决于操作数?例如,乘法11 * 13会比11111111 * 13131313?或者它总是花费最坏情况的时间?

cpu assembly x86-64 intel

5
推荐指数
2
解决办法
724
查看次数

方案中语法对象的目的究竟是什么?

我试图在python中编写一个类似于方案的小语言,以便更好地理解方案.

问题是我被困在语法对象上.我无法实现它们,因为我不太了解它们的用途以及它们的工作原理.

为了尝试理解它们,我在DrRacket中使用了语法对象.

从我能够发现的情况来看,评估#'(+ 2 3)与评估没有什么不同'(+ 2 3),除非在+顶级命名空间中存在一个词汇变量,在这种情况下(eval '(+ 2 3))仍会返回5,但(eval #'(+ 2 3))只会抛出错误.

例如:

(define (top-sym)
  '(+ 2 3))
(define (top-stx)
  #'(+ 2 3))
(define (shadow-sym)
  (define + *)
  '(+ 2 3))
(define (shadow-stx)
  (define + *)
  #'(+ 2 3))
Run Code Online (Sandbox Code Playgroud)

(eval (top-sym)),(eval (top-stx))(eval (shadow-sym))所有返回5,同时(eval (shadow-stx))抛出错误.他们都没有回来6.

如果我不知道更好,我会认为语法对象唯一特别的事情(除了他们存储代码位置以获得更好的错误报告的琐碎事实)是他们在某些情况下抛出错误符号对应物将返回可能不需要的值.

如果故事很简单,那么在常规列表和符号上使用语法对象就没有什么好处.

所以我的问题是:我对语法对象缺少什么让它们如此特别?

scheme eval hygiene racket syntax-object

5
推荐指数
1
解决办法
672
查看次数

在Go中,类型和指向类型的指针都可以实现接口吗?

例如,在以下示例中:

type Food interface {
    Eat() bool
}

type vegetable_s struct {
    //some data
}

type Vegetable *vegetable_s

type Salt struct {
    // some data
}

func (p Vegetable) Eat() bool {
    // some code
}

func (p Salt) Eat() bool {
    // some code
}
Run Code Online (Sandbox Code Playgroud)

难道VegetableSalt两个满足Food,即使一个是一个指针,另一个是直接一个结构?

struct pointers interface go

5
推荐指数
1
解决办法
5337
查看次数

有没有办法在Racket或任何其他Scheme中定义编译时(扩展时)宏变量?

举个简单的例子:

(define-macro-variable _iota 0) ; define-macro-variable does not really exist

(define-syntax (iota stx)
  (syntax-case stx ()
    ((iota)
     (let ((i _iota))
       (set! _iota (+ i 1))
       #`#,i))))
Run Code Online (Sandbox Code Playgroud)

这样给出:

(define zero (iota))
(define one-two-three (list (iota) (iota) (iota)))
(define (four) (iota))
Run Code Online (Sandbox Code Playgroud)

以下都应评估为#t:

(equal? zero 0)
(equal? one-two-three '(1 2 3)) ; possibly in a different order
(equal? (four) 4)
(equal? (four) 4)
(equal? (four) 4)
Run Code Online (Sandbox Code Playgroud)

是否有任何真正的球拍功能define-macro-variable可以完成上述示例中应该执行的操作?

编辑:

我找到了解决办法:

(define-syntaxes (macro-names ...)
  (let (macro-vars-and-vals ...)
    (values macro-bodies-that-nead-the-macro-vars ...)))
Run Code Online (Sandbox Code Playgroud)

但我更喜欢一种解决方案,它不需要使用宏变量的所有宏都在一个表达式中.

macros scheme define-syntax racket

5
推荐指数
1
解决办法
292
查看次数

我应该在头文件中包含<stdio.h>,这样我就可以声明一个带有FILE*的函数吗?

例如foo.h:

typedef struct foo_t foo_t;

/* Lots of function declarations dealing with foo_t... */

int foo_print(const foo_t *foo); /* Print foo to stdout. */
int foo_fprint(FILE *f, const foo_t *foo); /* Print foo to file f. */
Run Code Online (Sandbox Code Playgroud)

我不想丢弃foo.h太多其他用户foo.h可能不想包含的头文件,但我确实需要声明采用类型的函数FILE*.我怀疑自己是第一个遇到这种困境的人,所以在这种情况下人们通常会做些什么呢?或者我错误地想要避免包含stdio.h在我的头文件中?

编辑:

人们似乎不理解我的问题.澄清一下,这里有一些潜在的解决方案:

  1. 只需包含stdio.h而不用担心它会导致客户端代码发生冲突(例如,如果他们碰巧有自己的函数碰巧被调用getchar).
  2. 使用a #ifdef来查明是否stdio.h已经包含,然后才声明FILE*相关函数.这样做的缺点是它会#include在我的客户代码中强加一个特定的排序.
  3. 将所有与I/O相关的声明移动到单独的头文件,例如foo_io.h.

什么是最好的事情是什么问题?

c c++ coding-style declaration header-files

5
推荐指数
1
解决办法
1673
查看次数

有什么办法可以解决,包括一个无法访问的返回语句吗?

我有以下功能:

func fitrange(a, x, b int) int {
    if a > b {
        a, b = b, a
    }
    switch true {
    case x < a:
        return a
    case x > b:
        return b
    default:
        return x
    }
}
Run Code Online (Sandbox Code Playgroud)

go编译器抱怨"函数在没有return语句的情况下结束",即使语句中的每个可能路径都switch返回一个值.除了return在函数末尾添加一个虚拟语句之外,还有什么方法可以解决这个问题吗?

return go switch-statement

4
推荐指数
2
解决办法
442
查看次数

在python中,有没有办法让re.finditer将文件作为输入而不是字符串?

假设我有一个非常大的文件foo.txt,我希望在找到正则表达式时迭代它.目前我这样做:

f = open('foo.txt')
s = f.read()
f.close()
for m in re.finditer(regex, s):
    doSomething()
Run Code Online (Sandbox Code Playgroud)

有没有办法在不必将整个文件存储在内存中的情况下执行此操作?

注意:逐行读取文件不是一个选项,因为正则表达式可能跨越多行.

更新:stdin如果可能的话,我也希望这样做.

更新:我正在考虑以某种方式使用自定义文件包装器模拟字符串对象,但我不确定正则表达式函数是否会接受自定义的类似字符串的对象.

python regex file-io

4
推荐指数
2
解决办法
1447
查看次数

我可以在公共标头中而不是在私有标头中将变量声明为const吗?

例如,我可以做这样的事情,以便只能foo.c修改变量foo吗?:

foo.h:

extern const int foo;
void foo_init(void);
void foo_reinit(void);
Run Code Online (Sandbox Code Playgroud)

foo.private.h:

int foo;
void foo_init(void);
void foo_reinit(void);
Run Code Online (Sandbox Code Playgroud)

foo.c:

#include "foo.private.h"
void foo_init() { foo = 1; /* ... */ }
void foo_reinit() { foo++; /* ... */ }
Run Code Online (Sandbox Code Playgroud)

bar.c:

#include <foo.h>
int main()
{
    foo_init(); printf("foo: %d\n", foo);
    foo_reinit(); printf("foo: %d\n", foo);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

因此,以下将产生错误/警告:

baz.c:

#include <foo.h>
int main()
{
    foo_init(); printf("foo: %d\n", foo);
    foo = 0; /* ERROR/WARNING …
Run Code Online (Sandbox Code Playgroud)

c linker const header-files

4
推荐指数
2
解决办法
71
查看次数

如何使函数具有库内部链接?

举例来说,如果我有两个文件foo.cbar.o,并foo.c包含一个函数foo()引用的函数bar()bar.o:

int foo(int x) { x = bar(x); /* ... */ }
Run Code Online (Sandbox Code Playgroud)

如何编译暴露foo()但不暴露的静态或动态库bar()?换句话说,我想bar()只在库内链接.

c linker gcc compilation ld

4
推荐指数
1
解决办法
1434
查看次数