c-编译器如何区分int指针和char指针



我有一个int指针和一个char指针。

我知道那个指针只存储一个内存地址。现在,如果我有一个int指针,当我请求下一个值时,我的地址会增加4个字节。

现在,当我们请求下一个值时,int指针必须增加4个字节,char指针必须增加1个字节,我们在编译器或内存中的何处存储指令?

执行的操作由其操作数的类型决定。

考虑一个包含两个操作数p + n的"加号"运算。如果p的类型是"指向int的指针",而n的类型是int,则编译器生成指令来计算地址,该地址是p所指向的n乘以sizeof(int)字节。如果p的类型是"指向char的指针",而n的类型是int,则编译器生成指令来计算p所指向的地址之外的n乘以sizeof(char)字节的地址。

类似地,在表达式*p中,如果p的类型是"指向int的指针",编译器将生成一条从内存加载四字节整数的指令。如果p的类型是"指向char的指针",编译器会生成一条从内存加载一个单字节整数的指令。

对于下标运算,p[n]被定义为*((p(+(n((`,因此它是上述两个运算的组合。

(请注意,上述内容适用于孤立表达式的简单编译。总体而言,编译器可能会优化程序,因此生成的程序集可能与上述内容不同,但效果相同。(

增量存储在汇编代码中。你可能会看到eax+4或3[eax]的东西(顺便说一句,这两个不一样(。从本质上讲,汇编代码是在运行时告诉计算机如何增量。

编译器如何知道要执行此操作?这是来自编译器的代码。它创建了所谓的抽象系统树或更有用的图。这些图可以确保规则得到遵守,就像增量一样。

如果你对此感兴趣,可以读一本关于编译器和计算机体系结构的书。

试试吧。

int fun1 ( int *x )
{
unsigned int ra;
int sa;

sa=0;
for(ra=0;ra<100;ra++)
{
sa+=x[ra];
}
return(sa);
}
char fun2 ( char *x )
{
unsigned int ra;
char sa;

sa=0;
for(ra=0;ra<100;ra++)
{
sa+=x[ra];
}
return(sa);
}
char fun3 ( short *x )
{
unsigned int ra;
short sa;

sa=0;
for(ra=0;ra<100;ra++)
{
sa+=x[ra];
}
return(sa);
}
00000000 <fun1>:
0:   e3a02000    mov r2, #0
4:   e2403004    sub r3, r0, #4
8:   e2800f63    add r0, r0, #396    ; 0x18c
c:   e5b31004    ldr r1, [r3, #4]!
10:   e1530000    cmp r3, r0
14:   e0822001    add r2, r2, r1
18:   1afffffb    bne c <fun1+0xc>
1c:   e1a00002    mov r0, r2
20:   e12fff1e    bx  lr
00000024 <fun2>:
24:   e3a03000    mov r3, #0
28:   e2402001    sub r2, r0, #1
2c:   e2801063    add r1, r0, #99 ; 0x63
30:   e5f20001    ldrb    r0, [r2, #1]!
34:   e0833000    add r3, r3, r0
38:   e1520001    cmp r2, r1
3c:   e20330ff    and r3, r3, #255    ; 0xff
40:   1afffffa    bne 30 <fun2+0xc>
44:   e1a00003    mov r0, r3
48:   e12fff1e    bx  lr
0000004c <fun3>:
4c:   e3a03000    mov r3, #0
50:   e2402002    sub r2, r0, #2
54:   e280c0c6    add r12, r0, #198   ; 0xc6
58:   e1f210b2    ldrh    r1, [r2, #2]!
5c:   e0813003    add r3, r1, r3
60:   e1a00803    lsl r0, r3, #16
64:   e1a03000    mov r3, r0
68:   e152000c    cmp r2, r12
6c:   e1a00820    lsr r0, r0, #16
70:   e1a03843    asr r3, r3, #16
74:   1afffff7    bne 58 <fun3+0xc>
78:   e20000ff    and r0, r0, #255    ; 0xff
7c:   e12fff1e    bx  lr

你可以清楚地看到:

c:   e5b31004    ldr r1, [r3, #4]!
30:   e5f20001    ldrb    r0, [r2, #1]!
58:   e1f210b2    ldrh    r1, [r2, #2]!

您还可以看到半字和字节操作的处理(此体系结构使用32位寄存器(。

最新更新