gcc编译与vc编译器区别

来源:互联网 发布:linux基础教程视频 编辑:程序博客网 时间:2024/05/06 14:27

gcc编译器的功能强大,支持的语法也非常灵活,给我们在编程时带来了非常大的方便,也给移植代码时带来了一定的难度。 

1 声明64位数据类型:
gcc: long long
vc: __int64 

2 switch语法中的case语句:
gcc: case '0' ... '9'
vc: case 0:
     case1:
      ...

3 寄存器变量的作用范围:
gcc: 可以把register变量声明为全局或局部的
vc: 只能是局部变量

4 有符号和无符号整形:
gcc: 在常量数字后面加LL或ULL,例如:
无符号:0xffffffffffffffffULL
有符号:0xffffffffffffffffLL
vc: 在常量数字前加强制转换。例如:
无符号:(uint64_t)0xffffffffffffffff

5 宏变参
gcc: #define AAA(x...) 
vc: 不支持,在实际中碰到此类问题时只能根据代码分析实际情况将它分解成若干个宏

6 对数组中指定元素的初始化:
gcc: static int array[100] = { 
      [10] = 10, /* array[10] = 10; */
      [20] = 20, /* array[20] = 20; */
}
功能:通过这种方法,可在数组的声明当中就初始化指定元素的值,除了arrar[10]和array[20]外,其余元素会自动初始化为默认值,这给我们带来了一种很简捷的办法,这功能是不是很酷?

vc: 不支持,只能通过在指定元素前后填充0或另外写一个初始化函数来实现。如初始化函数可以这样写:
void init_array()
{
array[10] = 10;
array[20] = 20;
}

7 结构体的对齐:
 先解释一下如下几个属性关键字的含义:
1    属性 packed: 用于变量和类型,表示变量或结构域时使用最小可能的对齐,用于枚举、结构或联合类型时表示该类型使用最小的内存。
2    属性 aligned:用于变量、结构或联合类型,指定变量、结构域、结构或联合的对齐量,以字节为单位。                     
3   属性 noreturn:用于函数,表示该函数从不返回。这可以让编译器生成稍微优化的代码,最重要的是可以消除不必要的警告信息比如未初使化的变量。
4   属性 unused:用于函数和变量,表示该函数或变量可能不使用,这个属性可以避免编译器产生警告信息。
      如上这些关键字在gcc和vc中都是相对应的,只是使用的方法不一样。注意:vc必须装了service pack补丁后才支持。  

gcc:
struct __attribute__((packed)) st_syment
{
...
}

vc:
#pragma pack(push,1)
struct st_syment
{
...
}
#pragma pack(pop)
表示在这个结构体的元素是按字节对齐的。

gcc: __attribute__((aligned(16)))
vc: __declspec(align(16))
表示创建此结构体实例时按16字节对齐。

gcc: __attribute((noreturn))
vc: __declspec(noreturn)
表示此函数不需要返回。

8 得到当前函数的返回地址,就是这个函数被调用处的下条指令地址。例如:
push edx
call _func /* 调用名为func函数 */
pop edx
而在func()函数中又有这样一条语句:
void func()
{
... 
retaddr = __builtin_return_address(0); /* 此条语句执行后,retaddr的值应该是上面pop edx指令的地址 */
...
}

gcc: retaddr = __builtin_return_address(0)
vc: __asm { mov eax, [ebp+4] }
     __asm { mov retaddr, eax }
      我们知道,cpu执行一条指令时,eip总是指向下一条指令地址的,在调用一个函数前,就会先把eip入栈,以便函数返回后继续执行后面的指令,也就是说,在进入函数之前,栈顶(esp)的值就是eip了,所以我们就可以根据这个思路来解决。在vc编译后生成的汇编代码中,每个函数头部都有这样两条指令:
      push ebp
      mov ebp, esp
     就是将原来的esp放到ebp中了,加上前面一句push ebp,而压栈的顺序又是由高到低的,所以[ebp+4]就等于函数被调之前的eip。

原创粉丝点击