声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4256233.html

第四章     指针... 1
第五章     函数... 14
第六章     数组... 17
第七章     字符(串)/节... 25

第四章     指针

指针代表地址,即使用名字来替换地址,它或1的位,它们可以被解释为整数,也可以被解释为浮点数,这取决于被使用的方式。如果使用的是整型算术指令,这个值就被解释为整数,如果使用的是浮点型指令,它就是个浮点数。
 
 
指针图示:

注意箭头起始于方框内部,因为它代表存储于该变量的值。同样,箭头指向一个位置,而不是存储于该位置的值,这种记法提示跟随箭头执行间接访问操作的结果将是一个左值(即某个变量的地址,如&a,而不是某个变量a的值)。
 
 
    int *a;
    *a =12;
上面的程序是极为危险与错误的。这个声明创建了一个名叫a的指针变量,后面那个赋值语句把12存储在a所指向的内存位置。因为从未对a进行初始化,所以我们没有办法预测12这个值将存储于什么地方。虽然如果变量a是静态的它会被初始化为0,变量为自动的,它根本不会被初始化,但无论是哪种情况,
    a = &b;//初始化指针,让它指向某个确定的内存空间
    printf("%d\n", a);//现在指针所指向的位置为:2293576
    *a = 12;//将12常量存储到a所指向的某个内存位置
    printf("%d\n", *a);//12
    printf("%d", b);//12
 
NULL指针不指向任何东西。要使指针变量为NULL,你可以给它赋一个零。为了测试一个指针变量是否为NULL,你可将它与零值进行比较。之所以选择零这个值是因为一种约定,就不同机器内部而言,NULL指针实际值可能不是零,在这种情况下,只要使用NULL,编译器将负责零值和内部值之间的翻译转换工作。
 
如果对一个NULL指针进行间接访问会发生什么情况呢?结果会因编译器而异,在有些机器上,它会访问位置为零的地址中的内容,但这是极其错误的;在其他机器上,对NULL指针进行间接访问将引发一个错误,并终止程序,这种情况下程序员就很容易提示发现错误,如XP就是这样的:
    //将字符数组(字符串就是数组)首地址赋给p1
    char *p1="a" ;
    printf("%c",*p1);//a
    //将指针指向内存地址为0的位置
    char *p2=NULL ;
    printf("%c",*p2);//!!出错 
 
  
    int a;
    *&a=12;
上面程序的结果就是将12赋值给变量a。&操作符产生变量a的地址,它是一个指针常量,接着,*操作符访问其操作数所表示的地址,在这个表达式中,操作数是a的地址,所以25就存储到a中。这与  a = 12 有区别吗?从结果上讲没有区别,但它涉及到更多的操作。
 
假定a存储于位置100,下面这条语句合法吗?
*100 = 12;
这是错误的,因为字面值100的类型是整型值,而间接访问操作只能作用于指针类型表达式。如果你确实想把12存储于位置100,你必须使用强制类型转换:
从整型转换为指向整型的指针类型
虽然强转后合法,但通常我们不会这样作,因为我们无法预测编译器会把某个特定的变量放在内存中的什么位置,所以你无法预先知道变量a的地址。这个技巧除非用来访问内存中某个特定的位置,不是某个变量,而是访问硬件本身。
 
 
二级指针(指针的指针):
    int a = 12;
    int *b = &a;
    int**c = &b; 
 
表达式 等效的结果
a 12
b &a
*b a , 12
c &b
*c b , &a
**c *b , a, 12
 
 
 
 
 
 
各种指针表达式示例:
    char ch = 'a';
    char *cp = &ch;
现在我们有了两个变量,它们初始化如下:

表达式

右值

左值

描述

,再拷贝,椭圆即为拷贝出来的内容。

,椭圆即为拷贝出来的内容。

int a[][3] = { { 11, 12,14 }, { 21, 22, 23 } };
    int (*p)[3] = a;//数组指针
    //可以有以下四种方式访问a[1][0]元素,方括号[]比*优
    //先级高,所以下面是可以省略的
    printf("1、%d %d\n", a[1][0],p[1][0]);//21
    /*
     * (a+1)指向二维数组中的第二个元素数组;(a + 1)[0]在第二个元素数组中移动,
     * 即指向第二个元素数组中的首元素,结果是一个地址;*((a + 1)[0])取第二
     * 个元素数组中的首元素
     */
    printf("2、%d %d\n", *((a + 1)[0]),*((p + 1)[0]));//21
    /*
     * (a+1)指向二维数组中的第二个元素数组;(*(a + 1))取第二个元素数组,结果是
     * 一个一维数组;(*(a + 1))[0]取第二个元素数组中的首元素
     */
    printf("3、%d %d\n", (*(a + 1))[0],(*(p + 1))[0]);//21
    /*
     * a[1]指向第二个元素数组, *(a[1])取第二个元素数组中的首元素
     */
    printf("4、%d %d\n", *(a[1]),*(p[1]));//21
    /*
     * (a+1)指向二维数组中的第二个元素数组,*(a+1)取第二个元素数组,
     * **(a + 1)取第二个元素数组中的首元素
     */
    printf("5、%d %d\n", **(a + 1),**(p + 1));//21
 
    //在定义时可以不指定指针移动的单位,即指针单位长度
    //但如果不指定,则不能对指针进行移动操作,否则编译出错
    int (*p1)[] = a;
    //在不移动指针的条件下可以访问第一个元素
    printf("6、%d\n", **p1);//11
    //编译不能通过,因为上面在定义p1时未指定指针的最小移动单位
    //所以不能移动
    //  printf("%d", **(p1 + 1));
 
    //一维数组指针
    int b[]={1,2,3};
    int *p2=b;
    printf("7、%d\n", *(p2 + 1));//2
 
    //指定长度后就可以对指针进行移动
    int (*p3)[3] = a;
    /*
     * 以3个int为单位进行移动。(p3 + 1)在第一维中移动,
     * (*(p3 + 1)+1)在第二维中移动
     */
    printf("8、%d\n", *(*(p3 + 1)+1));//22
 
    //编译时警告。以2个int单位进行移动
    int (*p4)[2] = a;
    printf("9、%d\n", **(p4 + 1));//0

 
 
高效数组循环方法
float values[5];
float *vp;
for (vp = &values[0]; vp < &values[5];) {
    *vp++ = 0;
}
for语句使用了一个关系测试来决定是否结束循环,这是合法的,因为vp和指针常量都指向同一数组中的元素(事实上,这个指针常量所指向的是数组最后一个元素后面的那个内存位置,虽然在最后一次比较时,vp也指向了这个位置,但由于我们此时未对vp执行间接访问操作,所以它是安全的)
上面的循环等同于下面的循环:
for (vp = &values[5]; vp > &values[0];) {
    *--vp = 0;
}
但不能使用以下循环:
for (vp = &values[4]; vp >= &values[0];) {
    *vp-- = 0;
}
原因就是:比较表达式vp >= &values[0];的值未定义,因为vp移到了数组的边界之外。标准允许指向数组的指针与指向数组最后一个元素后面的那个内存位置的指针进行比较,但不允许与指向数组第一个元素之前的那个内存位置的指针进行比较。所以最后不要这样使用,但在大多数的编译器中能顺利的完成任务,但为了可移植性与稳定性,不能这样使用。
 
 
 
 
 
声明一个指针变量并不会自动分配任何内存。在对指针执行间接访问前,指针必须进行初始化:或者使它指向现有的内存,或者给它分配动态的内存。对未初始化的指针变量执行间接访问操作是非法的,而且这种错误常常难以检测。其结果常常是一个不相关的值被修改。这种错误是很难被调度发现的。
 
NULL指针就是不指向任何东西的指针。它可以赋给一个指针,用于表示那个指针并不指向任何值。对NULL指针执行间接访问操作的后果因编译器而异,两个常见的后果分别是返回内存位置零的值以及终止程序。
 
对指针执行间接访问操作所产生的值也是个左值,因为这种表达式标识了一个特定的内存位置。

第五章     函数

K&R C:
int *
find_int(key,array,array_len)
int key;
int array;
int array_len;
{}
但不能省略函数的大括号,所以不支持函数原型声明。
 
为了与ANSI标准之前的程序兼容性,没有参数的函数的原型应该写成下面这样:
int func(void);
 
当程序调用一个无法见到原型的函数时,编译器便认为该函数返回一个整型值。所有函数都应该具有原型,尤其是那些返回值不是整形的函数。
 
可变参数
可以使用<stdarg.h>中的一组宏定义来操纵可参数。
 
用法:     
(1)首先在函数里定义一具va_list型的变量,这个变量是指向参数的指针
(2)然后用va_start宏初始化变量刚定义的va_list变量,这个宏的第二个参数是省略号前最后一个有名字的参数。
(3)然后用va_arg返回可变的参数,va_arg的第二个参数是你要返回的参数的类型。如果函数有多个可变参数的,依次调用va_arg获取各个参数。
(4)最后用va_end宏结束可变参数的获取。
 
由于参数列表中的可变参数部分并没有原型,所以,所有作为可变参数传递给函数的值都将执行缺省参数类型提升()相乘。这个乘法需要花费一定的时间和空间。现使用指针来实现同样的功能:
    int array[10], *p;
    for (p = array; p < array + 10; p++) {
       *p = 0;
    }
现在这个乘法出现在for语句的调整部分,1这个值必须与整型的长度相乘,然后现与指针相加,但这里存在一个重大区别:循环每次执行时,执行乘法运算的都是两个相同的数(1和4),结果,这个乘法只在编译时执行一次,程序在运行时并不执行乘法运算,所以在运行时所需要的指令就少一些。
 
 
最高效的数组访问:
#define SIZE 50
int x[SIZE];
int y[SIZE];
//数组拷贝
int main() {
    registerint *p1, *p2;
    for (p1 = x, p2 = y; p1 < &x[SIZE];) {
       *p1++ = *p2++;
    }
}
结论:当你根据某个固定数目的增量在一个数组中移动时,不如使用指针变量将比使用下标产生效率更高的代码;声明为寄存器变量的指针通常比位于静态内存和堆栈中的指针效率更高;如果你可以通过测试一些已经初始化并经过调整的内容来判断循环是否该应该终止,那么你就不需要使用一个单独的计数器。
 
指针和数组
    int a[5];
    int *b; 

声明一个数组时,编译器将根据声明所指定元素数量为数组保留内存空间,然后再创建数组名,它的值是一个常量,指向这段空间的起始位置。声明一个指针变量时,编译器只为这个指针本身保留内存空间,它并不为任何整型值分配内存空间,而且,指针变量并未初始化为指向现有的有意义的空间。所以 *a 是完全合法的,但表达式 *b 却是非法的。*b将访问内存中某个不确定的位置,或者导致程序终止,另外,表达式b++可以通过编译,但a++却不行,因为a的值是个常量。
 
 
数组参数
数组名的值就是一个指向数组第一个元素的指针,所以传递给函数的是一份该指针的拷贝。函数如果执行了下标引用,实际上是对这个指针执行间接访问操作,并且通过这种间接访问,函数可以访问和修改主调程序的源数组元素。
 
传址调用是通过传递一个指向所需元素的指针,然后在函数中对该指针执行间接访问操作实现对数据的访问,而作为参数的数组名是个指针,下标引用实际执行的就是间接访问,所以传递数组时“好像”体现了传址,但本身却是传值,那数组的传值行为表现在什么地方呢?传递给函数的是参数的一份拷贝(指向数组起始位置的指针的拷贝),所以函数可以自由地操作它的指针形参,而不必提心会修改对应的作为实参的指针。所以并不矛盾:所有的参数都是通过传值方式传递的。
 
传递一个数组时,正确的函数形参应该是怎样的?它是应该声明为一个指针还是一个数组?调用函数时实际传递的是一个指针。但为了使用程序员新手更容易上手一些,编译器也接受数组形式的函数形参,下面两个函数原型是相等的:
int strlen(char * string);
int strlen(char string[]);
这个相等性暗示指针和数组名实际上是相等的,但千万不要被它糊弄了,这两个声明确实相等,但只是在当前这个上下文环境中。哪个“更加准确”呢?答案是指针,因为实际上是个指针,而不是数组,同样,表达式sizeof string的值是指向字符的指针的长度,而不是数组的长度:
int size1(int * a){
    returnsizeof a;
}
int size2(int  a[]){
    returnsizeof a;
}
int main() {
    int a[5];
    printf("%d\n",sizeof a);//20
    printf("%d\n",size1(a));//4
    printf("%d\n",size2(a));//4
}
现在你应该清楚为什么函数原型中的一维数组形参无需写明它的元素数目(如果是多维数组,则也只能省略第一维的大小),因为函数并不为数组参数分配内存空间。形参只是一个指针,它指向的是已经在其他地方分配好的内存的空间,它可以与任何长度的数组匹配。另一方面,这种实现方法使函数无法知道数组的长度,如果函数需要知道数组的长度,它必须作为一个显示的参数传递给函数。
 
不完整的初始化
    int vector[5] = { 1, 2, 3, 4, 5, 6 };
    int vector[5] = { 1, 2, 3, 4 };
第一个声明是错误的,我们没有办法把6个整型值装到5个整型变量中去,但第二个声明是合法的,最后一个元素初始化为0。另外,也只能省略最后元素的值,不能省略中间的。
 
自动计算数组长度
    int vector[] = { 1, 2, 3, 4 };
如果声明中并未给出数组的长度,编译器就把数组的长度设置为刚好容纳所有的初始值的长度。
 
字符数组的初始化
    char string1[] = { 'H', 'e', 'l', 'l', 'o', 0 };
    char string2[] = "Hello";
第二种看上去是一个字符串常量,实际上并不是(只是一个初始化列表),它只是第一个声明的另一种写法。那什么情况下"Hello"是一个字符串常量呢?要根据它所处的上下文来区分:当用于初始化一个字符数组时,它就是一个初始化列表,在其他任何地坟,它都表示一个字符串常量。
 
    char string1[] = "Hello";
    char *string2 = "Hello";
这两个初始化看上去很像,但它们具有不同的含义。第一个初始化一个字符数组的元素,而后者则是一个真正的字符串常量,这个指针变量被初始化为指向这个字符串常量的存储位置,并且这个位置的内容不能被修改: 
 
 
多维数组
多维数组在内存分配上与一维数组一样,在物理上没有区别,也是连续的,只是多维数组在逻辑上将元素划分为多个逻辑单位。
 
    int matrix[6][10];
    int *mp;
    matrix[3][8] = 38;
    matrix[3][9] = 39;
    matrix[4][0] = 40;
    mp = &matrix[3][8];
    printf("First value is %d \n", *mp);//38
    printf("Second value is %d \n", *++mp);//39
    printf("Third value is %d \n", *++mp);//40
这个例子使用一个指向整型的指针遍历存储了一个二维整型数组元素的内存空间,这个技巧被称为压扁数组,它实际上是非法的,因此从某行移到下一行后就无法回到包含第1行的那个子数组,尽管通常没有问题,但有可能的话还是应该避免这样使用。
 
多维数组名:
    int matrix[3][10];
matrix可以看作是一个一维数组,包含3个元素,只是每个元素又是包含了10整型元素的数组。matrix这个名字是一个指向它第1个元素的指针,所以matrix是一个指向一个包含10个整型元素的数组的指针
 
matrix[1][5] == *(*(matrix + 1) + 5) == *(matrix[1] + 5)
matrix 指向第一行,(matrix+1)指向第二行,*(matrix+1)代表第二行元素(第二维数组),既然*(matrix+1)又是一个数组,所以该表达式又代表了(matrix+1)指向的第二行子数组的首元素的地址,所以(*(matrix+1)+5)表示在(matrix+1)指向的第二行子数组中移动到第6个元素位置上,所以*(*(matrix+1)+5)代表了该位置上的元素。
 
int matrix[3,10];
在其他语言中表示二维数组,但在C中不是的,它是一个逗号表达式,最终的结果为matrix[10],而不是二维数组了
 
    int vector [10], *vp = vector;
    int matrix[3][10], *mp = matrix;
第一个表达式合法,vp与vector具有相同的类型,都是指向整型的指针;第二个声明非法,因为matrix并不是一个指向整型的指针,而是一个指向整型数组的指针,正确写法如下:
         int (*p)[10]= matrix;
(*p)[10]由于间接访问*的优先级低于数组下标访问,所以使用括号,这样就使 *p[10]从数组类型转换成了一个指针类型,p是一个指向拥有10个整型元素的数组的指针,使用它可以在matrix数组中一行一行的移动。上述表达式指向了matrix数组的第一行。
如果你需要一个指针逐个访问整型元素而不是逐行在数组中移动,你应该这样:
    int *pi=&matrix[0][0]; //第一个元素的地址
    int *pi=matrix[0];//第一个元素的地址也就是数组名
上面两个声明都创建了一个简单的整型指针,并以两种不同的方式进行初始化,指向matrix的第1个整型元素。
 
如果你打算在指针上执行任何指针运算,应该避免这种类型的声明:
    int (*p)[] = matrix;
p仍然是一个指向整型数组的指针,但 数组的长度没有,当与某个整型运算时,它的值将根据空数组来进行调整,即与零乘,这不是我们想要的。有些编译器要以捕捉到这类错误,但有些编译器却不能。
 
int matrix[3][10];
如果传递给一个函数,则函数的原型声明可以有以下两种:
void func(int(*p)[10]);
void func(int p[][10]);
但决不能是:
void func(int **p);
因为**p的类型为指向指针的指针,而(*p)[10]表示指向一个具有10元素的数组的指针。
 
多维数组的初始化可以像一维数组那样:
    int matrix[2][3] = { 1, 2, 3, 4, 5, 6 };
但Java不允许这样
 
    charconst* keyword[] = { "do", "for", "if", "register", "return",
           "switch", "while" };
    charconst**kwp = keyword;
keyword是一个指针数组,数组名keyword是一个二级指针(每个元素都是指针),其内存结构如下: 
 

charconstkeyword[][9] = { "do", "for", "if", "register", "return",
           "switch", "while" };
其内存结构如下: 

第七章     字符(串)/节

C语言并没有的字符串数据类型,因为字符串是以字符串常量的形式出现或者存储于字符数组中。个字符串不为空时才进行查找,如果s2为空,返回null
     */
    if (*s2 != '\0') {
       /*
        ** 查找s2在s1中第一次出现的位置
        */
       current = strstr(s1, s2);
 
       /*
        ** 每次找到字符串时,指向它的起始位置,然后查找该字符串下一个匹配位置。
        */
       while (current != NULL) {
           last = current;
           current = strstr(last + 1, s2);
       }
    }
    /*
     ** 返回指向我们找到的最后一次匹配的起始位置的指针
     */
    return last;
}
 
查找一个字符串前缀:
size_t strspn(charconst *str, charconst *group);
返回str起始部分匹配group中任意字符的字符数。例如,如果group包含了空格、制表符等空白字符,这个函数将返回str起始部分空白字符数目。下面的代码将计算一个指向字符串中第一个非空白字符的指针:
    char * ptr = buffer + strspn(buffer, "\n\r\f\t\v");
 
size_t strcspn(charconst *str, charconst *group);
strcspn正好与strspn相反,它对str字符串起始部分中不与group中任何字符匹配的字符进行计数。
示例:
    char buffer[] = "25,142,330,Smith,J,239-4123";
    int len1, len2;
    len1 = strspn(buffer, "0123456789");
    printf("%d\n", len1);//2
    len2 = strcspn(buffer, "ith");
    printf("%d\n", len2);//13
 
查找标记:
char * strtok(char * str,constchar *set)
strtok函数使用set字符串中的标记将字符串str分隔成不同的独立部分,每次可以返回这个独立部分。strtok函数找str中的标记后,使用NUL替换,并返回一个指向标记前的邻近字符串指针。如果函数的第一个参数str不为NULL,函数将查找字符串的第一个标记,如果为NULL,函数就从上一次查找的位置后开始查找标记。通常,第一次调用时传递一个字符串指针,以后,这个函数被重复调用(第一参数传递NULL),直到它返回NULL:
void print_tokens(char *line) {
    staticchar whitespace[] = " ,";
    char *token;
    for (token = strtok(line, whitespace); token != NULL; token = strtok(NULL,
           whitespace)) {
       printf("Next token is %s\n", token);
    }
}
int main() {
    char buffer[] = "a b,c";
    print_tokens(buffer);
}
由于strtok函数保存了处理过的函数的局部状态信息,所以
    printf("%c\n", memchr(a, 'b', 3) == NULL ? '0'
           : *(char *) memchr(a, 'b', 3));//b
 
memset函数把从aga vck r length个字节都设置为字符值ch,例如:
    memset(buffer, 0, SIZE);
把buffer的前个字节都初始化为0。
 

[C和指针]第二部分的更多相关文章

  1. C++二级指针第二种内存模型(二维数组)

    C++二级指针第二种内存模型(二维数组) 二维数组 二维数组本质上是以数组作为数组元素的数组,即“数组的数组”. 定义 类型说明符 数组名[常量表达式][常量表达式] 例如: float a[3][4 ...

  2. C学习笔记(5)--- 指针第二部分,字符串,结构体。

    1. 函数指针(function pointer): 函数指针是指向函数的指针变量. 通常我们说的指针变量是指向一个整型.字符型或数组等变量,而函数指针是指向函数. 函数指针可以像一般函数一样,用于调 ...

  3. LoadRunner 脚本学习 -- 指针基础

    先搞清楚 ++a 和 a++的区别 ++a : 前缀++,  先自增,后表达式 a++ : 后缀++,  先表达式,后自增 前缀,自增立即生效. 后缀,下次才会看到效果. 一维数组的指针 Action ...

  4. C语言 二级指针内存模型②

    //二级指针第二种内存模型 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #incl ...

  5. 全国计算机等级考试二级教程-C语言程序设计_第8章_地址和指针

    面试: unsigned int *p1 = &num; int *p2 = &num; #define _CRT_SECURE_NO_WARNINGS #include<std ...

  6. C和C指针小记(十三)-数组

    1.1 一维数组 一维数组的声明: int a[10]; 这里a就是一个数组. 数组a的类型就是一个指向整型的常量指针. 但是数组和指针是**不相同**的. **数组具有特定数量的元素,而指针只是一个 ...

  7. VB指针操作和消息钩子

    二.VB怎么用指针       要想弄明白VB怎么使用指针,就必须要弄明白两件事,第一,如何取得数组的指针,第二,如何将指针所指向的数组取出来.       A.在讲解这两个问题之前,我们需要了解几个 ...

  8. 第二百七十九节,MySQL数据库-pymysql模块操作数据库

    MySQL数据库-pymysql模块操作数据库 pymysql模块是python操作数据库的一个模块 connect()创建数据库链接,参数是连接数据库需要的连接参数使用方式: 模块名称.connec ...

  9. 【C++基础学习】引用和指针、重载、函数、内存管理

    第一部分:引用VS指针 引用的含义:变量的别名 注意:变量不能只有别名,必须有一个真实的变量与之相对应 基本数据类型的引用 对别名本身的操作和它的实体的操作是一样的 1.基本数据类型的引用 类型 &a ...

随机推荐

  1. Linux设备驱动之semaphore机制【转】

    转自:http://blog.csdn.net/xiao229404041/article/details/7031776 Linux设备驱动之semaphore机制在Linux系统中,信号号是一种重 ...

  2. 【Pro ASP.NET MVC 3 Framework】.学习笔记.9.SportsStore:Securing the Administration Features

    1 设置表单身份认证 因为ASP.NET MVC基于ASP.NET平台的核心,所以我们可以使用ASP.NET Form的身份认证,这是保持用户登录轨迹通用的方法.现在介绍最基本的配置. 在Web.co ...

  3. MySQL 获得当前日期时间 函数

    获得当前日期+时间(date + time)函数:now() mysql> select now(); +---------------------+ | now() | +---------- ...

  4. Linux下创建与解压tar, tar.gz和tar.bz2文件及压缩率对比 | 沉思小屋

    刚 在qq群里面一位仁兄问到文件压缩的命令,平时工作中大多用解压缩命令,要是遇到压缩就现查(这不是一个好习惯),于是整理下Linux下创建与解压 zip.tar.tar.gz和tar.bz2文件及他们 ...

  5. php blowfish加密解密具体算法

    PHP Blowfish 算法的加密解密,供大家参考,具体内容如下<?php/*** php blowfish 算法* Class blowfish*/class blowfish{/*** b ...

  6. php curl应该怎么使用呢

    原php默认并不进行此项功能的扩展,但还是有的,只是没有让它生效罢了.打开PHP安装目录,搜索以下三个文件 ssleay32.dll.libeay32.dll和 php_ curl .dll,一一拷贝 ...

  7. wordpress网站被挂马以及防御方法

    wordpress本身的安全性是非常的高的,一般不会被轻易的破解,被挂马,但是我们也不能够过度迷信wordpress的安全性,凡是连接上互联网的服务器和电脑,都存在被破解的风险性.所以我们在日常维护自 ...

  8. POSTGRESQL9.5之pg_rman工具

    pg_rman是一款专门为postgresql设计的在线备份恢复的工具.其支持在线和基于时间点备份方式,还可以通过创建backup catalog来维护DB cluster备份信息. 看起来好像是模仿 ...

  9. snackbar初体验

    底部弹出的部分就是snackbar的,右侧可添加一个action响应点击事件,遗憾的时貌似只能添加一个 这是华为mate8上面运行出来的效果,颜色之类的都是默认.不同的android版本样式稍有差异 ...

  10. cocos2dx lua bug之module 'lsqlite3' not found

    05-27 15:41:01.360: D/cocos2d-x debug info(7261): [LUA-print] -------------------------------------- ...