转:PHP程序员的C语言学习之路系列之第一章, C语言的一些基础

(1)  基本数据类型
     在学习PHP的时候你可能不用知道什么是数据类型, 就算PHP有很多数据类型如: “字符串类型”, “整数类型”, “浮点型类型”等, 但是PHP的数据类型跟C语言的数据类型还是有很大差别的. 为什么这样说? 因为PHP把C语言的数据类型抽象化了. 下面我们想来学习一下C语言的数据类型吧.
    PHP是弱类型语言, 而C语言是强类型语言, 也就是说如果你想使用C语言的变量, 那么你首先要知道变量的类型. 而不像PHP那样变量可以是任何的类型. 另外如果你想使用C语言的变量, 那么你必须先声明这个变量, 然后才可以使用. 如下:

int ivar;
ivar = 10;
如果你没有声明而直接使用变量, 编译会不通过, 如下是错误的:

ivar = 10;
因为PHP不用声明变量就能使用, 所以PHP程序员写C程序时要特别注意声明变量. C语言声明的方式是:
类型 变量名;

如:
int ivar; //定义一个名为ivar的整型变量
char cvar;//定义一个名为cvar的字符型变量
float fvar;//定义一个名为fvar的浮点型变量
double dvar1, dvar2, dvar3;//定义3个双精度类型的变量
long lvar1, lvar2, lvar3;//定义3个长整型的变量

阅读剩余部分...

转:PHP程序员的C语言学习之路系列之入门章编译环境的选择

声明: 首先这个教程是写给有PHP编程基础的童鞋们的, 所以如果你没有PHP编程基础的话, 我还是建议你先学习一下PHP的基础.
入门章, 编译环境的选择
C语言跟PHP不一样, PHP只有装个PHP解析器就可以运行了, 而C还要先编译才可以运行, 一般过程是这样:
c.jpg
C源代码编译之后可以直接在本机运行, 而不必像PHP那样要安装运行环境.
在编译这个过程我们需要一个C语言的编译器. C语言的编译器很多, 著名的有gcc, vc++(IDE)等. 我个人偏向gcc, 因为VC++只能在win平台下使用令人不爽. 不过初学者可以选择安装VC++6.0, 这个版本比较小, 而且容易使用. 我下面介绍一个也挺适合初学者使用的, 就是codeblocks.
先去官网下载一个codeblocks(http://www.codeblocks.org/), 安装完毕后就有编译器和IDE了, 所以挺好用的. 打开codeblocks这样:


好了, 我们试试这个IDE吧.

我们先选择菜单栏的: File -> New -> Empty file, 然后输入以下代码:

#include <stdio.h>
#include <stdlib.h>
int main() {

    printf("Hello World\n");

    return 0;

}
然后保存文件为test.c, 保存后按运行,嗯, 程序运行了, 如下:
helloworld.jpg
这个就是经典的“Hello World”程序了. 以后我们就可以用这个IDE来编写我们的程序了.如果你想使用VC++的话, 可以上网找一下关于VC++的使用的教程, 在这里我就不说了.
因为这章是入门章节, 所以我也不多说了, 下章就开始学习C语言了.

转自:http://blog.sina.com.cn/s/blog_7530db6f0100ppa3.html

找到一个win上安装GCC环境的好东西

     本人最烦linux,虽然装了个ubuntu的虚拟机和一个红旗的非主流系统,但几十年不去碰一下,除了调试工程偶尔开一下,懒得来回改HOST,基本很少用。不过我倒是很想在win上装个GCC,这个开发即快捷,又跨平台,还不影响我看片听歌。
     先是装了个codeblock 10的版本,觉得这软件挺好的,但是比较郁闷的是它的代码提示插件怎么弄也不起作用,还有就是编译速度太慢。最后发现某网友制作的msys集合包,使用后感觉贼好。特分享下。
     地址:http://code.google.com/p/msys-cn/.下面是它的简介:
  • MSYS不是一个操作系统,而是一个通过将Linux源代码在Win32上编译而成的UNIX工作环境;
  • MSYS类似于Cygwin,但是由于工作原理的不同,速度更快、体积更小、功能强大、便于携带;
  • 使用MSYS可以完整的取代商业的VC环境,同样开发出商业版权的程序而不受任何版权限制;
  • 本项目开发了mpkg包管理程序,添加对各种开源库支持,提供MSYS发行版的方便下载服务;
  • 默认提供捆绑在一起的ASM/C/C++/ObjC/ObjC++/Fortran编译器,便捷的适用于各种用户;
  • 编译器中预先配置好了所需的DK、PthreaDDK、DirectX 9 Sd库,无需再自己搜集组合;
  • 更新的4.3.2版本GCC编译器为C/C++/Fortran用户提供了内建的OpenMP并行计算支持;
  • 本项目的初衷,是为Phoenix操作系统开发项目提开发环境,因而适合OS开发爱好者使用;
  • 项目通过GNU开发的info帮助系统提供了所有命令的帮助手册,开发者应当用MSDN作为函数手册;


php在win下调用C++写的EXE示例

    几天前,有一位童鞋在夜色群里提到到php在windows下与exe程序的交互。当时看了下他写的C程序,就发觉其思路不对,不过那天刚回到公司比较颓废也就懒得动手了。趁着这几天有空,再写写这方面的东西,其实很简单,权当抛砖引玉。这方面的资料不多,虽然说php在win下调exe有点蛋疼,不过蛋疼就蛋疼吧,权当玩玩。
    结合网上提供的C++操作sqlite的方法,我们来写一个稍微复杂的应用,体验一下。
   首先用vc2008写一个exe程序,代码如下:
#include "stdafx.h"
#include <string>
#include <iostream>
#include <sstream>
#include "../sqlite3_lib/sqlite3.h"
/**
演示php调用C++进行数据操作的过程。
**/

阅读剩余部分...

PE文件初探二

上一篇主要是很初略的总结了是什么,这篇要总结下为什么。以下部分参照了http://msdn.microsoft.com/en-us/magazine/cc301727.aspxhttp://blog.donews.com/zwell/archive/2005/10/21/596302.aspx两位大牛的文章。和上述不同的是本文主要的涉及内容来自win7。当然我这里并没有真正的涉及win7,以及Vista所加入的新内容,(因为那些对现在的我来说实在是太复杂了)。win7 只是一个壳子,我描述的核心是在win2K,甚至是在windows3.1这些版本中就已经有的。当然为了能够更详细的理解整个过程。反汇编了部分loader的源代码。 pseudocode下载

当然,我看到的windows loader的代码对我来说依然是非常庞大,这里仅仅记录了程序正确路线,并没有完善错误路线,往往是return error来结束。当然,在代码中,难免有错误,特别是对我来说,这是第一次从汇编角度观察windows。也希望各位大牛,能够帮我指出里面的错误。

一开始本来是想长篇大论的去写这一篇文章,因为涉及到的内容实在太多。而且大部分都是再重复大师们的内容。这里实在是不敢造次。仅仅记录一些自己认为有必要重复和自己所遇到的问题。上面2篇文章非常值得研究,如果你也对这方面感兴趣。

最后,由于最近时间很紧,代码还是缺少了一些部分。还有相当一部分需要去完善细节,现在之所以记录,仅仅害怕时间长了。自己会懒惰而没有记下这个过程。当然,我会在这个《PE文件初探系列》的最后补全代码。

当我们调用LoadLibraryEx LoadLibrary类似的函数,我们会进入到LdrpLoadDll,就让我们从它开始载入过程。

LdrpLoadDll的大体思路Russ Osterlund,已经解释的很清楚了。为了查阅方便,原谅我这里只是简单翻译重复一下。

阅读剩余部分...

PE文件初探一

最近一直在学习PE文件的相关知识。随着了解的增多,我不得不改变之前的学习方式。以前总是再理解更进一步后, 才总结上一层的知识。而且理解知识的时候总是喜欢从难到易得方式去理解知识。因为如果漫无目的的去学习,实在是 一个体力活。如果把一系列相关的知识比作一颗倒置的二叉树的话,我总是喜欢从根节点开始,然后再去遍历每个叶子 节点。只可惜我并没有掌握非递归算法。好吧,再没有处理尾递归的情况下,随着二叉树深度的增加。我的堆栈也果断溢 出。并导致一度中断学习过程。。。。。。。。。虽然我不断地去增加堆栈空间。但是总会有不能再增加的时候。好吧, 就是现在。该让我好好处理这个尾递归的问题。这也就是这篇文章的目的了。

  闲话扯得太多了。这篇文章主要内容是DLL的载入过程分析。以下部分主要来自《windows核心编程》和一些网上资料。 当然,如果想仔细理解相关内容。那么这3篇文章你是不该错过的。http://msdn.microsoft.com/zh-cn/magazine/cc301727(en-us).aspxhttp://msdn.microsoft.com/en-us/magazine/cc301808.aspxhttp://msdn.microsoft.com/en-us/magazine/cc301805.aspx 事实上,你可能 还需要非常非常多的延伸知识需要帮助理解。如果对这部分知识不是很了解。而且英文也不是很好的话,《软件加密 技术内 幕》中的前几章的相关讲解,可能会更加易懂,还有老罗的书《Windows环境下32位汇编语言》,当然。这里讲的是最最基础 的部分。而且事实上,那3篇英文的分量对我来说还是很重的。这也是造成我堆栈溢出的原因。而且我脑子现在还没从错误中 恢复过来。。。。。

1.1 简短的背景知识

在操作系统中,执行的代码在载入内存之前,是以文件的方式存放在磁盘中。为了灵活的使用代码,在代码之前增加 一个文件头,在文件头中包括各种数据,文件入口,重定位表等信息。操作系统根据给定的信息,将部分代码载入内存,初始 化必要数据后,最后从指定位置开始执行。

1.2 开始了解PE

阅读剩余部分...

标题:堆和栈的区别 (转)

一、预备知识—程序的内存分配 
由C/C++编译的程序占用的内存分为以下几个部分 
1、栈区(stack): 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 
2、堆区(heap): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。 
3、全局区(static): 全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,程序结束后有系统释放 。 
4、文字常量区: 常量字符串就是放在这里的, 程序结束后由系统释放。 
5、程序代码区: 存放函数体的二进制代码。 
Example: 
int a = 0; // 全局初始化区 
char *p1; // 全局未初始化区 
main() 

int b; // 栈 
char s[] = "abc"; // 栈 
char *p2; // 栈 
char *p3 = "123456"; // 123456\0在常量区,p3在栈上。 
static int c =0; // 全局(静态)初始化区 
p1 = (char *)malloc(10); 
p2 = (char *)malloc(20); // 分配得来得10和20字节的区域就在堆区。 
strcpy(p1, "123456"); // 123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。 


二、堆和栈的理论知识 
2.1 申请方式 
栈: 由系统自动分配。 例如,声明在函数中一个局部变量 int b; 系统自动在栈中为b开辟空间 
堆: 需要程序员自己申请,并指明大小,在c中malloc函数:如p1 = (char *)malloc(10); 在C++中用new运算符 如p2 = (char *)malloc(10); 但是注意p1、p2本身是在栈中的。 
2.2 申请后系统的响应 
栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。 
堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时, 会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块 内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的 大小,系统会自动的将多余的那部分重新放入空闲链表中。 
2.3 申请大小的限制 
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因 此,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。 
2.4 申请效率的比较: 
栈:由系统自动分配,速度较快。但程序员是无法控制的。 
堆:是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便。 
另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存,他不是在堆,也不是在栈是直接在进程的地址空间中保留一快内存,虽然用起来最不方便。但是速度快,也最灵活。 
2.5 堆和栈中的存储内容 
栈: 在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由 右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址, 也就是主函数中的下一条指令,程序由该点继续运行。 
堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。 
2.6 存取效率的比较 
char s1[] = "aaaaaaaaaaaaaaa"; 
char *s2 = "bbbbbbbbbbbbbbbbb"; 
aaaaaaaaaaa是在运行时刻赋值的; 
而bbbbbbbbbbb是在编译时就确定的; 
但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。 
比如: 
#include 
void main() 

char a = 1; 
char c[] = "1234567890"; 
char *p ="1234567890"; 
a = c[1]; 
a = p[1]; 
return; 

对应的汇编代码 
10: a = c[1]; 
00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh] 
0040106A 88 4D FC mov byte ptr [ebp-4],cl 
11: a = p[1]; 
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h] 
00401070 8A 42 01 mov al,byte ptr [edx+1] 
00401073 88 45 FC mov byte ptr [ebp-4],al 
第一种在读取时直接就把字符串中的元素读到寄存器cl中,而第二种则要先把指针值读到edx中,在根据edx读取字符,显然慢了。 
2.7 小结: 
堆和栈的区别可以用如下的比喻来看出: 使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是 快捷,但是自由度小。 使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。 
还有就是函数调用时会在栈上有一系列的保留现场及传递参数的操作。栈的空间大小有限定,VC的缺省是2M。栈不够用的情况一般是程序中分配了大量 数组和递归函数层次太深。有一点必须知道,当一个函数调用完返回后它会释放该函数中所有的栈空间。栈是由编译器自动管理的,不用你操心。堆是动态分配内存 的,并且你可以分配使用很大的内存。但是用不好会产生内存泄漏。并且频繁地malloc和free会产生内存碎片(有点类似磁盘碎片),因为C分配动态内 存时是寻找匹配的内存的。而用栈则不会产生碎片。在栈上存取数据比通过指针在堆上存取数据快些。一般大家说的堆栈和栈是一样的,就是栈(stack),而 说堆时才是堆heap。栈是先入后出的,一般是由高地址向低地址生长。

转:C语言的几个谜题

这几天,本站推出了几篇关于C语言的很多文章如下所示:



我们可以看到很多C语言相关的一些东西。比如《语言的歧义》主要告诉了大家C语言中你意想不到的错误以及一些歧义上的东西。而《谁说C语言很简单》则通过一些看似你从来不可能写出的代码来告诉大家C语言并不是一件容易事情。《6个变态的hello world》和《如何弄乱C的源代码》则以一种极端的方式告诉大家,不要以为咱们自己写不出混乱的代码,每个程序员其实都有把代码搞得一团乱的潜质。通过这些文章,相信你对编程或是你觉得很简单的C语言有了一些了解。是的,很不容易吧,以前是不是低估了编程和C语言?今天是否我们又在低估C++和Java呢?

本篇文章《C语言的谜题》展示了14个C语言的迷题以及答案,代码应该是足够清楚的,而且我也相信有相当的一些例子可能是我们日常工作可能会见得到的。通过这些迷题,希望你能更了解C语言。如果你不看答案,不知道是否有把握回答各个谜题?让我们来试试。

阅读剩余部分...

    Page :
  1. 1
  2. 2
  3. 3