0

在哪里可以找到++数字和指针运算符的 C/C++ 实现?

我浏览了网络,但没有找到太多...

4

4 回答 4

6

该实现位于编译器的源代码中。

通常,您的编译器将执行以下操作:

  • 推断 的类型i
  • 如果i是纯整数类型或对整数的引用,编译器将生成一个中间表示,指示从内存加载(如果需要)和简单的 +1 增量。
  • Ifi是一个指针,编译器将生成一个中间表示,指示从内存加载(如果需要),然后是一个添加指令,sizeof(*i)而不是 +1。
  • Ifi是重载operator++()在作用域内的类型,它会生成一个中间表示,指示对重载运算符定义的函数调用。

这里没有魔法。i++通常映射到整数类型的简单addinc指令,并可能映射到 C++ 中的函数调用。

于 2013-01-05T06:09:43.957 回答
4

可能是我的答案(数字)在某种程度上有帮助:
你可以驱动指针的答案

如何i++在低级别工作。

int main(){
    int i=0,j=0;
    j=i++;  // expresion includes two operations `+, =      
    printf("%d %d",j,i);
}

您可以使用以下-S标志对其进行反汇编gcc (g++)
我的代号是m.c

$ gcc -S m.c

它将创建一个m.s程序集文件。

阅读我添加的评论:

pushl   %ebp
movl    %esp, %ebp
andl    $-16, %esp
subl    $32, %esp

movl    $1, 28(%esp)            // i due to declarations 
movl    $0, 24(%esp)            // j

movl    28(%esp), %eax          // this two lines are j = i
movl    %eax, 24(%esp)

addl    $1, 28(%esp)            // increment to i, i++

movl    $.LC0, %eax
movl    28(%esp), %edx
movl    %edx, 8(%esp)
movl    24(%esp), %edx
movl    %edx, 4(%esp)
movl    %eax, (%esp)
call    printf

这就是分配=首先发生的方式++。如果++是后缀。

编译器的工作原理:

(根据我的编译器)

对表达式的抽象语法树进行自下而上的评估j = i ++

源代码:

j = i++;  

在低级别分为两条指令(如您在汇编代码中所见):
j = i i++

i++在哪里i = i + 1

// abstract syntax tree

       + (post)
      / \
     /   \  
    =     1 
   / \       
  /   \
 j     i  

前缀的情况++(++i):

还假设如果表达式是j = ++i那么我直接编写抽象语法树:

它会先递增++然后=执行;

// abstract syntax tree for j = ++i  

    =
   / \       
  /   \
 j     \ 
       + (prefix)
      / \
     /   \  
    i     1 

j = ++i哪里j=0i=1最初 的汇编代码:

movl    $1, 28(%esp)          // i declaration 
movl    $0, 24(%esp)          // j  
addl    $1, 28(%esp)          // First  Add 1 to i because i++ (before = perform)
movl    28(%esp), %eax        // Below two steps: = performed  j = i 
movl    %eax, 24(%esp)
于 2013-01-05T06:13:24.910 回答
3

我认为您想查看为此操作生成的机器代码。这里 :

//sg
int main()
{
    int i=0;
    ++i;
    return 0;
}

编译:gcc -S -fverbose-asm -masm=intel test.c

这是程序集(相关部分):

mov DWORD PTR [ebp-4], 0    # i,
add DWORD PTR [ebp-4], 1    # i,

将此与

//sg
int main()
{
    int i=0,j;
    j=i+1;
    return 0;
}

这将产生更长的 asm :

mov DWORD PTR [ebp-4], 0    # i,
mov eax, DWORD PTR [ebp-4]  # tmp62, i
add eax, 1  # tmp61,
mov DWORD PTR [ebp-8], eax  # j, tmp61

另请注意,现代编译器会自动更改i=i+1为更短的i++.

于 2013-01-05T06:10:48.480 回答
1

嗯,这是一个非常基本的问题,你最好从教科书中学习

但不管怎么说

对于数字

内置++将数值加 1,改变内存内容。您可以在整数和浮点对象上使用此运算符。您可以将它用作前缀运算符 writing++x和作为后缀运算符 writing x++

区别在于前缀和后缀变体产生的表达式值。前缀++x递增x并产生的新值x(在 C++ 中,我记得它产生对 , 的引用x,带有新值)。后缀x++递增x并产生 的原始x

用于指针

前缀和后缀的区别是一样的,但是“加1”的定义不同

对于指向T*T 数组的第 i 个项的类型的指针,在递增该指针后,它指向数组的第 i+1 个项。

这意味着机器代码级地址增加了sizeof(T).

如果最终值定义明确,则表达式p+nwhere nis an integer 产生与增量相同的最终值。n这也可以写成n+p

于 2013-01-05T06:14:28.363 回答