您的位置:首页 > 数据库 > MySQL

MySQL参数优化

2008-04-24 13:27 183 查看
一、指针基础:
指针其实就是地址,指针变量就是存储地址的变量。只不过我们通常看到的是变量存储整形,字符型等这样的变量。指针变量,唯一特殊的,存放的是地址变量。通常一个指针变量所占的存储空间是8个字节。
int i = 5;
int *p; //定义一个指针类型的变量

p = &i; //p 里面存放的是i这个变量的地址

int *q; //定义一个q指针变量

q = &p; //q里面存放的是一个指向p的地址。

如下图所示:




指针变量p 本身的地址是:0X3000,其实其存储空间的内容是0X2000.同理q是一个指向p的指针。有了指针,我访问i值得方法就很多了。

例如:int a;

a = i //把i的值5 赋值给a变量

a = *p //*是取值运算。意思是:取出p变量所存储的地址指向空间的值。显然是5

a = **q //*q的意思同上,即是:0X2000,那么 **q的含义就是取出0X2000地址所指向的存储空间的值,就是5.

二、指针辨析
2.1、空指针和野指针
空指针:定义方式是:void *p = NULL;任何类型的指针都可以赋值给空指针。当不确定指针类型的时候可以先申明成空指针。

野指针:int *p;只有定义,没有初始化,也就是不清楚指针所指向的地址到底是哪儿。非常危险。通常定义指针,可以 int *p = NULL;全0的地址空间,OS是不分配给任何空间使用的。所以可以确保安全。

2.2、指针与一维数组的关系:
例如:

int a[3] = {1,2,3};

int *p;

p = a;

需要注意的是:数组是一段连续的存储空间。数组名a就是数组的起始地址。所以可以将a直接赋值给指针变量p

a本身就是地址的话。那么*a就相当于相当于*p,就是去a数组的第一个元素值。*(a+1)就是取第二个元素的值。

a本身是数组。但是a是常量,常量在程序的使用过程中可以参与运算,但是值不能被修改。所以*(a++)是错误的。p是指针变量。值是可以改变的。所以*(p++)是可以的。

a[i] 和*(a+i)和 *(p+i);

2.3、指针与二维数组
int a[2][3] = {{1,2,3},{4,5,6}};
需要理解二维数组的存储规律
二维数组可以看成多个一维数组组成。例如。上述的二维数组可以看成,两个三个元素的一维数组组成的。
二维数组是以行顺序存储的。



数组名a同上也是一个地址。a的值是0X2000,但是定义int *p; p=a 是错误的。编译的时候会产生警告。因为。a是地址,但是a是一个行地址。a指向的地址不仅只有一个数据元素,而是3个数据元素【元素的个数取决于二维数据的列元素的个数】。那么a+1 指向的 就是第二行了。具体地址如图上:0X2012.

a[0]是一个列指针,指向的是一个一维数组的起始地址。a[0]的值和a一样都是0X2000,值一样,但是含义不同。a[0]等价于*(a+0).【此时的*相当于将a这样行地址降级为列地址。】所以*a+1指向的地址是0X2004. 那么a[0][1] 等价于 *(*a+1).
int a[2][3]={{1,2,3},{4,5,6}};
int *p;
p = *a;
//下面的两行输出完全一样

printf ("%p---->%d\n",p+1,*(p+1)); //需要彻底理解p此时作为列指针的用法
printf ("%p---->%d\n",&a[0][1],a[0][1]);

//典型的把二维数组当一维数组使用。同时,按行顺序存储得到验证。

p = &a[0][0];
printf ("%p----->%d\n",p+4,*(p+4));

二维数组与指针结合使用:int *p ; *p = *a;【*p=*a 的含义是将第一列的首地址赋给p,p+1 指向第一行的第二个元素。就是p+1 的值是:0X2004】.通过此种方式定义列地址,把二维数组抽象成一维数组进行遍历使用。【int *p = &a[0][0],也是没有问题的】

也可以通过定义数组指针的方式,使用二维数组。数组指针,就是一个指针类型,它指向的是一个数组。具体定义方式如下:
int a[2][3]={{1,2,3},{4,5,6}};
int (*p) [3] = NULL;//数组指针的定义方式。3取决二维数组的列元素个数
//p此时跟a的用法基本等价,只不过p可以自增自减,a是常量,不可以
//a+1 和p+1一样都是指向下一行的第一个元素

p = a;
//以下三行输出完全一样

printf("%p--->%d\n",(*(p+1)+1),p[1][1]);
printf("%p--->%d\n",&a[1][1],a[1][1]);
printf("%p--->%d\n",&p[1][1],a[1][1]);
2.5、指针常量与常量指针的关系

指针常量:落脚点常量。所以首先是一个常量,只不过这个常量是指针的。而且这个常量的值不能修改。说白了就是指针的指向不能改变

示例:

int i = 5;
int j = 3;
int * const p = &i; //注意定义方式
p = &j; //这句是有错误的。错误在于,p是常量指针,指向是不能改变的。
常量指针:落脚点是指针。首先是个指针。这个指针指向的是常量。也就是指针指向的内容是不允许修改的。但是指针的指向是可以改变的。

示例:
#if 0
//int *p = &i;
//*p = 6; // 通过此种方法可以强行改变一个常量的值
#endif
int const *p = &i;
*p = 6 //此时编译报错,不能改变指针常量所指向的值。
const int *const p; 即是常量指针,又是指针常量,就是说,既不能改变指向,也不能改变指向的值
2.6、函数传参是指针与数组的关系:

一维数组:
int a
;

int *p = a;

实参形参
a 【地址】int *p
p 【地址】int *p
a[0] 【整值】int a
p+1【地址,第二个元素地址】int *p
a+1【地址,第二个元素地址】int *p
&a[3]【地址,第四个元素地址】int *p
*p【整值:第0个元素值】int a
*a【整值,第0个元素值】int a
二维数组:

int a[M]
= {,,,,,,,,};

int *p = *a //注意是个列指针哦
int (*q)
= a //是一个指向N个元素的行指针


实参形参
a[i][j] 【整形值】int a
*(a+i)+j 【a[i][j]的地址】 int *p
*(*(a+i)+j)【整型值】int a
a[i]+j 【a[i][j]的地址】int *p
p[i] 【第0行第i个元素地址】int *p
*p 【a[0][0]的值,整型值】int a
q[i][j] 【a[i][j]的值,整型值】int a
*q 【a[0][0]的地址,需要好好理解】int *p
q 或 a 【二维数组起始地址】 int (*p)
p+3 【第0行第三个元素地址】int *p
q+2 【第二行地址】int (*p)
2.7、指针函数、函数指针、函数指针数组
1、指针函数:说到底是函数,函数的返回值是指针类型

int * func(形参列表);

2、函数指针:说到底是指针,指针指向的函数的入口地址。

示例:

#include <stdlib.h>

int add (int a,int b)
{
return a+b;
}

int sub (int a, int b)
{
return a-b;
}

int main()
{
int a=3,b=5;
int val;
//定义函数指针:含义是:定义一个指针,指向的是一个函数,通过指针名调用函数
int (*p) (int,int);
// 注意第一个int 同要指向的函数的返回值类型,后两个int 同函数的形参列表。
int (*q) (int ,int);
p = add;
// p = add 也可以写成 p = &add 是一样的。也就是说在函数指针的环节,可以省略 &取地址,* 取值
q = sub;
val = p(a,b);
printf("add result is %d \n",val);
val = q(a,b);
printf("sub result is %d \n",val);
exit(0);
}

3、函数指针数组:首先是一个数组。数组的内容是一个函数指针。什么函数指针,就是一个指针,指向函数的所以总体说来是一个指向函数的指针组成的数组

定义形式:

类型 (* 数组名[下标]) (形参)

int (*funcp[2]) (int ,init);
定义了一个名叫funcp的数组,大小为2. 2个元素的内容是指向返回值是int,有两个int形参的函数

#include <stdio.h>

#include <stdlib.h>

int add (int a,int b)
{
return a+b;
}

int sub (int a, int b)
{
return a-b;
}

int main()
{
int a=3,b=5;
int val;
//定义函数指针:含义是:定义一个指针,指向的是一个函数,通过指针名调用函数

int (*funcp[2]) (int ,int);

funcp[0] = add;

funcp[1] = sub;
val = funcp[0](a,b);
printf("add result is %d \n",val);
val = funcp[1](a,b);
printf("sub result is %d \n",val);
exit(0);
}
本文出自 “hylinux” 博客,请务必保留此出处http://hongyilinux.blog.51cto.com/8030513/1738485
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: