当前位置: 首页 > wzjs >正文

中小企业网站设计与开发目的做网站用哪个软件

中小企业网站设计与开发目的,做网站用哪个软件,广州网站推广模板,网页搭建初衷目录 1. 数组名的理解(数组首元素地址还是整个数组) 2. 使用指针访问数组 3. 一维数组传参的本质 4. 二级指针(指针变量的指针,存放指针变量的地址) 5. 指针数组 6. 数组指针变量 6.1 数组指针变量的初始化 7.…

目录

1. 数组名的理解(数组首元素地址还是整个数组)

2. 使用指针访问数组

3. 一维数组传参的本质

4. 二级指针(指针变量的指针,存放指针变量的地址)

5. 指针数组

6. 数组指针变量

6.1 数组指针变量的初始化

7. 二维数组传参的本质(传递的是第一行这个一维数组的地址)

8. 字符指针变量

8.1 字符数组和常量字符串的区别

8.2 常量字符串的存储 

9. 函数指针变量

9.1 函数指针变量的创建

9.2 函数指针变量的使用

9.3 两个代码(难理解)

9.4 typedef 关键字(类型重命名)

10. 函数指针数组

11. 函数指针数组实现计算器(函数指针数组—转移表)

11.1 计算器一般实现

11.2 改进1—函数指针数组方式

11.3 改进2—函数指针作参数(回调函数)


1. 数组名的理解(数组首元素地址还是整个数组)

        数组名就是数组首元素(第一个元素)的地址是对的,但是有两个例外:

                • sizeof(数组名),sizeof中单独放数组名,这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节

                • &数组名,这里的数组名表示整个数组,取出的是整个数组的地址(整个数组的地址和数组首元素的地址是有区别的:地址相同,但是类型不同

        除此之外,任何地方使用数组名,数组名都表示首元素的地址

数组和指针的关系:

        1.数组就是数组,是一款连续的空间(数组的大小和数组元素的个数和类型都有关系)

        2. 指针(变量)就是指针(变量),是一个变量(4/8个字节

        3. 数组名是地址,是首元素的地址

        4. 可以使用指针来访问数组

2. 使用指针访问数组

#include <stdio.h>
int main()
{int arr[10] = { 0 };int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);//输入int* p = arr;for (i = 0; i < sz; i++){scanf("%d", p + i);//scanf("%d", arr+i);//也可以这样写}//输出for (i = 0; i < sz; i++){//printf("%d ", *(p + i));printf("%d ", p[i]);}return 0;
}

        将 *(p+i) 换成 p[i] 也是能够正常打印的,所以本质上 p[i] 是等价于 *(p+i) 。

        同理 arr[i] 应该等价于 *(arr+i) ,数组元素的访问在编译器处理的时候,也是转换成首元素的地址+偏移量求出元素的地址,然后解引用来访问的。

        即:arr[i] <=> *(arr+i) <=> p[i] <=> *(p+i)

        其实:arr[i] <=> *(arr+i) <=> *(i+arr) <=> i[arr]    (但是后面的方式不推荐使用)

        [ ] 是下标引用操作符,是下标引用操作符:arr[i] => *(arr+i)   ==   i[arr] => *(i+arr)

3. 一维数组传参的本质

#include <stdio.h>// 数组传参的时候,形参是可以写成数组的形式的
// 但是本质上还是指针变量
void Print(int arr[10])	// int* arr
{int sz2 = sizeof(arr) / sizeof(arr[0]);	// 得不到元素的个数// 这里的arr已经单纯是数组首元素的地址了,sizeof(arr)就是指针的大小printf("sz2 = %d\n", sz2);
}int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int sz1 = sizeof(arr) / sizeof(arr[0]);	printf("sz1 = %d\n", sz1);Print(arr);// 只有sizeof(arr),&arr 这两种情况才数组名才代表的是整个数组,所以此处给Print的参数只是数组首元素的地址!!!return 0;
}

        我们发现在函数内部是没有正确获得数组的元素个数。

        只有sizeof(arr),&arr 这两种情况才数组名才代表的是整个数组,所以此处给Print的参数给的数组名只是数组首元素的地址!!!那么在数组传参的时候,传递的是数组名,也就是说数组传参本质上传递的是数组首元素的地址

        形参的数组是不会单独再创建数组空间的,所以形参的数组是可以省略掉数组的大小的。(即形参可以写成:int arr[ ] )

        所以函数形参的部分理论上应该使用指针变量来接收首元素的地址。那么在函数内部我们写sizeof(arr) 计算的是一个地址的大小(单位字节)而不是数组的大小(单位字节)。正是因为函数的参数部分是本质是指针,所以在函数内部是没办法求的数组元素个数的。(下面代码为:指针变量接收首元素的地址

#include <stdio.h>// 数组传参的时候,形参是可以写成数组的形式的
// 但是本质上还是指针变量
//void Print(int arr[10])	// int* arr
//{
//	int sz2 = sizeof(arr) / sizeof(arr[0]);	// 得不到元素的个数
//	printf("sz2 = %d\n", sz2);
//}void Print(int* p, int sz)
{for (int i = 0; i < sz; i++){printf("%d ", *(p + i));}
}
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int sz1 = sizeof(arr) / sizeof(arr[0]);	printf("sz1 = %d\n", sz1);Print(arr);return 0;
}

        总结:一维数组传参,形参的部分可以写成数组的形式,也可以写成指针的形式。

4. 二级指针(指针变量的指针,存放指针变量的地址)

#include <stdio.h>int main()
{int a = 10;int* p = &a;	// 一级指针int** pp = &p;	// 二级指针// int* 说明pp指向的p的类型是int*,*说明pp是指针变量printf("%p\n", *pp);    // pp解一层引用是p,即&aprintf("%p\n", p);printf("%p\n", &a);printf("%d\n", **pp);   // pp解两层引用是*p,即aprintf("%d\n", a);return 0;
}

5. 指针数组

        整型数组,是存放整型的数组,字符数组是存放字符的数组。那指针数组则是存放指针的数组

        指针数组的每个元素都是用来存放地址(指针)的。指针数组的每个元素是地址,又可以指向一块区域。

6. 数组指针变量

        前面讲的 指针数组 是一种数组,数组中存放的是地址(指针)。

        数组指针变量指针变量存放的是数组的地址,能够指向数组的指针变量。

int *p1[10];    // 指针数组,p1[10]是数组,int*是数组类型
int (*p2)[10];  // 数组指针,int (*)[10] 是指针类型
p先和*结合,说明p是一个指针变量变量,然后指着指向的是一个大小为10个整型的数组。
所以p是一个指针,指向一个数组,叫 数组指针。

        注意:[ ]的优先级要高于*号的,所以必须加上()来保证p先和*结合。

6.1 数组指针变量的初始化

#include<stdio.h>
int main()
{int arr[10] = { 0 };int(*p)[10] = &arr;	//&arr得到的就是数组的地址return 0;
}
int (*p) [10] = &arr;
|     |    |
|     |    |
|     |    p指向数组的元素个数
|     p是数组指针变量名
p指向的数组的元素类型

7. 二维数组传参的本质(传递的是第一行这个一维数组的地址

        二维数组起始可以看做是每个元素是一维数组的数组。那么二维数组的首元素就是第一行,是个一维数组。

        根据数组名是数组首元素的地址这个规则,二维数组的数组名表示的就是第一行的地址,是一维数组的地址。根据上面的例子,第一行的一维数组的类型就是int [5] ,所以第一行的地址的类型就是数组指针类型int(*)[5] 。那就意味着二维数组传参本质上是:传递的是第一行这个一维数组的地址,那么形参也是可以写成指针形式的。如下:int(*arr)[5]

        总结:二维数组传参,形参的部分可以写成数组,也可以写成指针形式。

#include<stdio.h>//void Print(int a[3][5], int r, int c)
void Print(int(*arr)[5], int r, int c)
{int i = 0;for (i = 0; i < r; i++){int j = 0;for (j = 0; j < c; j++){printf("%d ", *(*(arr + i) + j));}printf("\n");}
}
int main()
{int arr[3][5] = { {1,2,3,4,5}, {2,3,4,5,6},{3,4,5,6,7} };// 数组名是数组首元素的地址// 1.&数组名// 2.sizeof(数组名)Print(arr, 3, 5);return 0;
}

8. 字符指针变量

8.1 字符数组和常量字符串的区别

        常量字符串不能修改!!!

#include <stdio.h>int main()
{char ch = 'w';char* pc = &ch;char arr[10] = "abcdef";char* p1 = arr;     // p1指向的是字符数组的首元素,可以修改*p1 = 'w';  // 可以修改//char* p2 = "abcdef";    const char* p2 = "abcdef";// p2指向常量字符串的首元素,所以不能修改,最好用const修饰//*p2 = 'w';// 不能修改printf("%s\n", p1); // 都可以用%s打印printf("%s\n", p2);return 0;
}

8.2 常量字符串的存储 

#include <stdio.h>
int main()
{char str1[] = "hello world.";char str2[] = "hello world.";const char* str3 = "hello world.";const char* str4 = "hello world.";if (str1 == str2)printf("str1 and str2 are same\n");elseprintf("str1 and str2 are not same\n");if (str3 == str4)printf("str3 and str4 are same\n");elseprintf("str3 and str4 are not same\n");return 0;
}

        这里str3和str4指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域当几个指针指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同,str3和str4相同。

9. 函数指针变量

9.1 函数指针变量的创建

        函数指针变量是用来存放函数地址的,未来通过地址能够调用函数的。

        函数名就是函数的地址,也可以通过&函数名的方式获得函数的地址

        注意:这里和数组的区别,数组名是数组首元素地址,&数组名是整个数组的地址,两个地址相同,但是类型不同!!!而函数名和&函数名完全相同

#include <stdio.h>
void test()
{printf("hehe\n");
}
int main()
{printf("test: %p\n", test);printf("&test: %p\n", &test);return 0;
}
// 输出结果
// test: 005913CA
// &test: 005913CA

        函数指针变量的写法其实和数组指针非常类似。如下:

void test()
{printf("hehe\n");
}
void (*pf1)() = &test;
void (*pf2)() = test;int Add(int x, int y)
{return x + y;
}
int(*pf3)(int, int) = Add;
int(*pf3)(int x, int y) = &Add;//x和y写上或者省略都是可以的

        函数指针类型解析: 

int (*pf3) (int x, int y)
|      |     ------------
|      |           |
|      |           pf3指向函数的参数类型和个数的交代
|      函数指针变量名
pf3指向函数的返回类型int (*) (int x, int y) // pf3函数指针变量的类型
int (*) (int, int)     // x和y写上或者省略都是可以的

9.2 函数指针变量的使用

        通过函数指针调用指针指向的函数

#include <stdio.h>
int Add(int x, int y)
{return x + y;
}
int main()
{int(*pf3)(int, int) = Add;printf("%d\n", Add(2, 3));printf("%d\n", (*pf3)(2, 3));printf("%d\n", (&Add)(2, 3));printf("%d\n", pf3(2, 3));return 0;
}

9.3 两个代码(难理解)

#include <stdio.h>
int main()
{( * ( void (*)() ) 0 )();// void (*)() -- 函数指针类型// ( void (*)() ) -- 强制类型转换// ( void (*)()) ) 0 -- 将0强制类型转换位void (*)()的函数指针类型// 这就意味着我们假设0 地址处存放着 无参,返回类型是void的函数// 最终调用0地址处存放的这个函数return 0;
}
// 函数声明
void (* signal(int, void(*)(int)))(int);
//void (*)(int) signal(int, void(*)(int)); //err
//上一行写法错误,但是好理解,signal是函数名,void (*)(int)是函数的返回类型

9.4 typedef 关键字(类型重命名)

typedef unsigned int uint;	//将 unsigned int 重命名为 uint
typedef int* ptr_t;			//将 int* 重命名为 ptr_t;	//对于数组指针和函数指针稍微有点区别:
typedef int(*parr_t)[5];	//将 int(*)[5] 重命名为 parr_t , 新的类型名必须在*的右边,
typedef void(*pfun_t)(int); //将 void(*)(int) 重命名为 pfun_t , 新的类型名必须在*的右边// 简化9.3的代码2可以写成:
typedef void(*pfun_t)(int);
pfun_t signal(int, pfun_t);

10. 函数指针数组

        把函数的地址存到一个数组中,那这个数组就叫函数指针数组

#include <stdio.h>int  Add(int x, int y)
{return x + y;
}int  Sub(int x, int y)
{return x - y;
}int  Mul(int x, int y)
{return x * y;
}int  Div(int x, int y)
{return x / y;
}
int main()
{int (*pf1)(int, int) = Add;    int (*pfarr[4])(int, int) = { Add, Sub, Mul, Div };// int (*)(int, int)类型的数组for (int i = 0; i < 4; i++){int ret = pfarr[i](8, 4);printf("%d\n", ret);}return 0;
}

11. 函数指针数组实现计算器(函数指针数组—转移表)

11.1 计算器一般实现

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>void menu()
{printf("*************************\n");printf("****** 1:add 2:sub ******\n");printf("****** 3:mul 4:div ******\n");printf("****** 0:exit      ******\n");printf("*************************\n");printf("请选择:");
}int add(int a, int b)
{return a + b;
}int sub(int a, int b)
{return a - b;
}int mul(int a, int b)
{return a * b;
}int div(int a, int b)
{return a / b;
}int main()
{int input = 0;int x = 0;int y = 0;int ret = 0;do{menu();scanf("%d", &input);switch (input){case 1:printf("输入操作数:");scanf("%d %d", &x, &y);ret = add(x, y);printf("ret = %d\n", ret);break;case 2:printf("输入操作数:");scanf("%d %d", &x, &y);ret = sub(x, y);printf("ret = %d\n", ret);break;case 3:printf("输入操作数:");scanf("%d %d", &x, &y);ret = mul(x, y);printf("ret = %d\n", ret);break;case 4:printf("输入操作数:");scanf("%d %d", &x, &y);ret = div(x, y);printf("ret = %d\n", ret);break;case 0:printf("退出程序\n");break;default:printf("选择错误\n");break;}} while (input);return 0;
}

11.2 改进1—函数指针数组方式

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>void menu()
{printf("*************************\n");printf("****** 1:add 2:sub ******\n");printf("****** 3:mul 4:div ******\n");printf("****** 0:exit      ******\n");printf("*************************\n");printf("请选择:");
}int Add(int a, int b)
{return a + b;
}int Sub(int a, int b)
{return a - b;
}int Mul(int a, int b)
{return a * b;
}int Div(int a, int b)
{return a / b;
}int main()
{int x, y;int input = 1;int ret = 0;int(*p[5])(int x, int y) = { 0, Add, Sub, Mul, Div }; //转移表do{menu();scanf("%d", &input);if ((input <= 4 && input >= 1)){printf("输入操作数:");scanf("%d %d", &x, &y);ret = (*p[input])(x, y);printf("ret = %d\n", ret);}else if (input == 0){printf("退出计算器\n");}else{printf("输入有误\n");}} while (input);return 0;
}

11.3 改进2—函数指针作参数(回调函数)

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>void menu()
{printf("*************************\n");printf("****** 1:add 2:sub ******\n");printf("****** 3:mul 4:div ******\n");printf("****** 0:exit      ******\n");printf("*************************\n");printf("请选择:");
}
int Add(int a, int b)
{return a + b;
}
int Sub(int a, int b)
{return a - b;
}
int Mul(int a, int b)
{return a * b;
}
int Div(int a, int b)
{return a / b;
}// 函数指针作 calc函数的参数
void calc(int (*pf)(int, int))
{int x = 0;int y = 0;int ret = 0;printf("输入操作数:");scanf("%d %d", &x, &y);ret = pf(x, y);printf("ret = %d\n", ret);
}int main()
{int input = 0;do{menu();scanf("%d", &input);switch (input){case 1:calc(Add);break;case 2:calc(Sub);break;case 3:calc(Mul);break;case 4:calc(Div);break;case 0:printf("退出程序\n");break;default:printf("选择错误\n");break;}} while (input);return 0;
}

http://www.dtcms.com/wzjs/42197.html

相关文章:

  • 网站两侧广告看片应该搜什么关键词哪些词
  • 软件开发外包管理seo查询平台
  • 大型企业网络建设方案软件优化
  • 求好心人给个地址seo管理系统培训运营
  • 台州做网站最好的重庆百度推广优化
  • 做网站送邮箱全网热度指数
  • 网站加强阵地建设与管理关键词查询神器
  • 如何做logo模板下载网站seo搜索引擎优化人员
  • 申请了域名先做网站还是先备案软文范文大全
  • 中企动力科技股份有限公司佛山分公司seo专家是什么意思
  • wordpress 流量统计插件网络营销中的seo与sem
  • 批量建设新闻网站郑州网络营销哪个好
  • 国基建设集团有限公司网站友情链接的作用大不大
  • 现在学做网站赚钱吗网络广告营销有哪些
  • 如何制作一个公司网站腾讯企点怎么注册
  • WordPress建站布置怎么开通网站
  • 网站谷歌地图提交周口网络推广公司
  • dw软件可以做哪些网站网络营销与传统营销的区别
  • 临朐网站制作哪家好怎么才能在百度上打广告
  • 可以做公司宣传的网站有哪些灯塔网站seo
  • 北京做网站的开发公司北京网站优化服务商
  • 028网站建设工作室web网页
  • 合肥市建设工程造价管理站网站榆林市网站seo
  • 南京网站建设 seo网页设计培训学校
  • 响应式网站科技百度推广服务费一年多少钱
  • 手机上可以做网站seo单页面优化
  • .东莞网站建设网络推广方案范文
  • 长寿网站建设免费单页网站在线制作
  • 网站建设官网制作平台百度网址安全中心
  • 个人备案的域名拿来做别的网站seo专员岗位职责