C++基本语法,入门及提高(6)

来源:互联网 发布:php 一致性hash算法 编辑:程序博客网 时间:2024/06/01 07:19

>  4字节内存对齐

  4字节对齐就是指针的强制类型转换。一个简单的理解:不管src指针是什么类型的,在函数内统统转成char型指针 //Note:可能不是char,反正该类型的位宽 必然等于 CPU内的通用寄存器的位宽,即32位。这样*(char *)dst = *(char *)src;一次就会搬运4个字节。

> C发送Http请求和创建多线程?

C语言实现的HTTP请求- http://download.csdn.net/download/linyoujushi/2189519

> gcc编译与g++编译
 1.对于.c文件gcc当做c语言处理,g++当做c++处理;对于.cpp文件gcc和g++均当做c++处理;
 2.g++编译时实际上是调用gcc进行编译;
 3.gcc不能自动链接库文件,一般用g++来链接库文件,非要用gcc的话,一般使用gcc -lstdc++命令;
 4.extern “c”对于gcc和g++没有区别;
 5.实际使用时只需安装gcc和g++中的一个就行了,如果使用gcc,编译直接用gcc就行了,链接要加上-lstdc++参数;如果使用g++,编译时实际还是调用gcc,链接直接使用g++即可;
   关于包含库文件头文件的说明:以gtd库文件为例,库文件一般是libgtd.so格式的文件,如果是libgtd-***.so或者其他格式,可以通过软链接命令转化成libgtd.so格式,ln -s libgtd-***.so libgtd.so。一般库文件如果是放在/lib,/usr/lib,/usr/local/lib目录下,则无需额外处理,编译链接时-lgtd会自动找到对应文件不会报错,但是如果不在对应目录,则需要加上-L /所在目录 -lgtd才能找到对应的库文件。头文件一般是采用源文件中用#include命令包含,而不是采用-include参数包含,头文件如果放在/usr/include目录下则会自动找到不会报错,否则编译链接时需要使用-I /所在目录才能正确找到。 
编译链接命令示例: 
g++ test.cpp -o test.txt -L /mytest/lib -lgtd -I /mytest/include

> 创建多线程 C/C++
linux下C/C++,多线程pthread- http://www.cnblogs.com/xianghang123/archive/2011/08/11/2134927.html
“多线程”简介及其C代码实现框架- http://blog.csdn.net/zhouzhaoxiong1227/article/details/49870093
C语言中的多线程编程- http://www.cnblogs.com/renyuan/archive/2012/11/26/2789139.html

值得注意的是在gcc编译时不会出错,但是用g++就会有问题:invalid conversion from `void*' to `void*(*)(void*)

> C发起Http请求


> C/C++文件读写

C、C++一次将整个文件读入内存- http://blog.csdn.net/cashey1991/article/details/6769038
C语言中将结构体写入文件- http://blog.csdn.net/mbshqqb/article/details/52825696
C/C++文件读写操作总结- http://www.cnblogs.com/jianyungsun/archive/2011/02/19/1958587.html

> C/C++ 静态链接库(.a) 与 动态链接库(.so)
g++(gcc)编译选项
 -shared :指定生成动态链接库。
 -static :指定生成静态链接库。
 -fPIC :表示编译为位置独立的代码,用于编译共享库。目标文件需要创建成位置无关码,念上就是在可执行程序装载它们的时候,它们可以放在可执行程序的内存里的任何地方。
 -L. :表示要连接的库所在的目录。
 -l:指定链接时需要的动态库。编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.a/.so来确定库的名称。
 -Wall :生成所有警告信息。
 -ggdb :此选项将尽可能的生成gdb的可以使用的调试信息。
 -g :编译器在编译的时候产生调试信息。
 -c :只激活预处理、编译和汇编,也就是把程序做成目标文件(.o文件)。
 -Wl,options :把参数(options)传递给链接器ld。如果options中间有逗号,就将options分成多个选项,然后传递给链接程序。
  静态和动态链接库的选择要视情况而定。一般比较推荐动态链接方式,因为可以很好的节约内存,而且方便以后的库文件升级。
程序的静态链接,动态链接和装载- http://www.cnblogs.com/acSzz/p/5743789.html

> C/C++中struct与union的区别. Union: 共用体;Struct:结构体
  1.在存储多个成员信息时,编译器会自动给struct第个成员分配存储空间,struct 可以存储多个成员信息,而Union每个成员会用同一个存储空间,只能存储最后一个成员的信息。
  2.都是由多个不同的数据类型成员组成,但在任何同一时刻,Union只存放了一个被先选中的成员,而结构体的所有成员都存在。
  3.对于Union的不同成员赋值,将会对其他成员重写,原来成员的值就不存在了,而对于struct 的不同成员赋值 是互不影响的。
  注:在很多地方需要对结构体的成员变量进行修改。只是部分成员变量,那么就不能用联合体Union,因为Union的所有成员变量占一个内存。eg:在链表中对个别数值域进行赋值就必须用struct.

  C/C++的数据类型包括基本数据类型和非基本数据类型,基本数据类型就是整型、实型等,非基本数据类型也称为构造数据类型,包括数组类型、结构体类型和共用体类型。其中结构体类型和共用体类型分别通过关键字struct和union来声明或定义。

#include<stdio.h>
union union_data0{
        int a ;//本身占用4个字节
        char b ;//本身占用1个字节
        int c ;
};
union union_data1{
        short a;//本身占用2个字节
        char b[13];//本身占用13个字节
        int c ;//本身占用4个字节
};
struct struct_data{
        int a ;//int本身占用4个字节,偏移量为0
        char b ;//char本身占用1个字节,偏移量为4
        int  c ;//1.暂时偏移量为5,编译器会判断出5不是4的整数倍,会在b的后面填充3个字节,最后c的偏移量为8,使得c的偏移量为c本身大小的整数倍;2.现在整个结构体大小暂时为12,编译器会判断12是不是其最大成员的整数倍,会在c末尾填充为整数倍,最后得出结果为12
};
int main(int argv,char* args[])
{
        printf("%lu\n",sizeof(union union_data0)) ;
        printf("%lu\n",sizeof(union union_data1));
        printf("%lu\n",sizeof(struct struct_data)) ;
        return 0;
}

为什么要字节对齐?
答:是为了能让计算机快速读写,是一种以时间换取空间的方式。

> c指针??
 int p; //这是一个普通的整型变量  
 int *p; //首先从P 处开始,先与*结合,所以说明P 是一个指针,然后再与int 结合,说明指针所指向的内容的类型为int 型.所以P是一个返回整型数据的指针  
 int p[3]; //首先从P 处开始,先与[]结合,说明P 是一个数组,然后与int 结合,说明数组里的元素是整型的,所以P 是一个由整型数据组成的数组  
 int *p[3]; //首先从P 处开始,先与[]结合,因为其优先级比*高,所以P 是一个数组,然后再与*结合,说明数组里的元素是指针类型,然后再与int 结合,说明指针所指向的内容的类型是整型的,所以P 是一个由返回整型数据的指针所组成的数组  
 int (*p)[3]; //首先从P 处开始,先与*结合,说明P 是一个指针然后再与[]结合(与"()"这步可以忽略,只是为了改变优先级),说明指针所指向的内容是一个数组,然后再与int 结合,说明数组里的元素是整型的.所以P 是一个指向由整型数据组成的数组的指针  
 int **p; //首先从P 开始,先与*结合,说是P 是一个指针,然后再与*结合,说明指针所指向的元素是指针,然后再与int 结合,说明该指针所指向的元素是整型数据.由于二级指针以及更高级的指针极少用在复杂的类型中,所以后面更复杂的类型我们就不考虑多级指针了,最多只考虑一级指针.  
 int p(int); //从P 处起,先与()结合,说明P 是一个函数,然后进入()里分析,说明该函数有一个整型变量的参数,然后再与外面的int 结合,说明函数的返回值是一个整型数据  
 Int (*p)(int); //从P 处开始,先与指针结合,说明P 是一个指针,然后与()结合,说明指针指向的是一个函数,然后再与()里的int 结合,说明函数有一个int 型的参数,再与最外层的int 结合,说明函数的返回类型是整型,所以P 是一个指向有一个整型参数且返回类型为整型的函数的指针  
 int *(*p(int))[3]; //可以先跳过,不看这个类型,过于复杂从P 开始,先与()结合,说明P 是一个函数,然后进入()里面,与int 结合,说明函数有一个整型变量参数,然后再与外面的*结合,说明函数返回的是一个指针,,然后到最外面一层,先与[]结合,说明返回的指针指向的是一个数组,然后再与*结合,说明数组里的元素是指针,然后再与int 结合,说明指针指向的内容是整型数据.所以P 是一个参数为一个整数据且返回一个指向由整型指针变量组成的数组的指针变量的函数. 

函数指针: 指向函数的指针变量。
指针函数: 带指针的函数,也就是返回指针的函数。

指针数组: 首先它是一个数组,数组的元素是指针,也成为“存储指针的数组”。
数组指针: 首先它是一个指针,它指向一个数组,也可以理解为“数组的指针”。 也可以利用前面的“解读方法”去分析。
原创粉丝点击