• 关于

    字符指令是什么

    的搜索结果

回答

其实在内存上没什么差别,但编译器知道,m是字符串数组,x是字符指针。于是在编译sizeof(m)的时候,编译器生成指令去根据当前内存管理方式找到申明的数组长度编译器生成指令返回数组长度,在编译sizeof(x)的时候,编译器生成指令直接返回指针大小。中间更正一下,sizeof的值就是在编译时确定的其实像你例子这样得情况下,编译器根本不用生成指令去找那些长度,因为编译时数组长度已经确定,所以m的长度7就在指令里作为操作数了。一般free malloc出来的空间才会去找。总之,,编译器已经看透了一切。。

a123456678 2019-12-02 02:39:12 0 浏览量 回答数 0

问题

关于C语言链接,深入理解计算机系统里的问题

杨冬芳 2019-12-01 19:32:55 918 浏览量 回答数 1

回答

include 包含其他库、类、接口等的头文件。预处理器实际上就只是把整个头文件复制到你的源代码里面 (是的,这就是包含防御之所以是件好事的原因了). define 谁会不喜欢宏呢! 预处理器会把所有定义的实体替换成被定义的代码. 定义会一直持续直到发现这个定义的 #undef 指令. ifdef 条件行为告诉预处理器包含在遇到声明的条件成立的条件块中的代码. 你可以就像if-else语句一样使用它们,从这里面选择: #ifdef, #ifndef, #if, #else, 以及 #elif, 而你总是要使用一个 #endif 作为结束。leoxuleoxu翻译于 1年前0人顶顶 翻译的不错哦! error #warning 用来向用户发送消息。预处理器会在 #error 处, 而不会在 #warning 处停下来. 两种情况下他都会发送他在指令背后(的括号里面)发现的字符串, 发送到屏幕作为输出,因此它是一种确保针对你的平台一切OK的手动方式. line 用来在你遇到编译错误时修改显示的错误行号和文件名. 例如,加入你需要查看一个来自编译的中间文件的源文件(可能是自动生成的). pragma 其它由编译器解释的特殊指令。你的编译器文档会告诉你指令是怎么用的,而你不要假定他们在全世界都通用哦.leoxuleoxu翻译于 1年前0人顶顶 翻译的不错哦! assert #unassert 这些在老程序里面总是特别受欢迎的 (好吧,只要我也曾经为这样一个程序工作过), 但是它们在现在已经过时了。强烈建议不使用它们,这意味着不要把他们放到新的代码里面预定义宏 有许多可以利用的预定义宏:FILE 给出一个字符串的文件名LINE 给出当前的行号(整型)DATE 当前编译日期的字符串TIME 当前编译时间的字符串STDC 同编译器相关的,但常常被定义成1,以声明同ISO C标准兼容.__cplusplus 在编译一个C++程序是总是会被定义特别是开头两个在调试时真的非常有用。只要拿出它们俩,不用你自己编写文件和行处理类,就能神奇的让你获得丰富的信息输出.leoxuleoxu翻译于 1年前0人顶顶 翻译的不错哦!你的编译器可能还支持其它的宏,例如,你这从 这里 获得(面向GCC)的整个宏清单.那么当你运行预处理器时实际会发生什么呢? 替换所有的三字母组合,我会在将来的一篇文章中谈论到他,因为尽管他只是一个历史上的特性(而且你也要在GCC中对它进行切换),它仍让是很有趣的. 将并列的源代码分成多行. 移除所有的注释并用一个空格替换. 处理(我们上面讲到的)的预处理器指令。对于 #include, 他会在新文件上递归执行1 - 3步 :-) 处理转义序列. 把文件发送给编译器 如果你想看看预处理之后你的文件会是什么样子 (谁不想呢?),你可以向 gcc 传入 -E 选项. 这将会想stdout标准输出发送预处理过的源代码,并且没有编译和连接就直接终止gcc命令的执行。具体实例如下:`1g++ -E myfile.cpp`你也可以使用这个参数:`1-save-temps`编译的后会有一份临时文件。拿下面这个简单的程序说吧: 1#include <stdio.h> 2 3#define ONE 1 4#define TWO 2 5 6int main() 7{ 8 printf("%d, %d\n", ONE, TWO); 9 return 0; 10} 用下面这行命令编译`1g++ hello.cpp -save-temps`编译完后, 会在文件夹中生成两个文件: hello.s 和 hello.iihello.s 里面是汇编代码, 而 hello.ii 则是预处理过后的源代码。用文本编辑器打开 hello.ii , 你会发现多出许多代码. 那是因为 #include 指令把 stdio 头文件的代码加进去了。如果你把滚动条拉到最底下, 就会发现, printf 那一行的宏定义 ONE 和 TWO 已经被预处理器替换成 1 和 2 了 .神奇吧!其实它只是在编译的时候, 把你的源代码文件复制一份, 当作临时文件, 然后把里面的预处理指令替换掉. 用完后就把这个临时文件删了. 所以一般情况下我们不知道这个文件的存在.

a123456678 2019-12-02 01:56:33 0 浏览量 回答数 0

阿里云试用中心,为您提供0门槛上云实践机会!

0元试用32+款产品,最高免费12个月!拨打95187-1,咨询专业上云建议!

回答

你要知道mysql是以客户端client /服务端server的结构运作:YOU比喻成M女士,客户端比喻作土豪金版iphone,客户端比喻作007。当你要007去执行任务时就必须通过iphone(好吧,我知道这有点牵强orz)流程:你-->通过iphone发送指令-->007去执行 在mysql里,client与server之间的数据是通过TCP/IP协议传输的:亦就是讲,要将client的数据发送到server上要通过TCP/IP协议管道,反之,server要将数据回送到client上,亦要通过TCP/IP协议管道传输。 这里全文上下所讲的数据就是二进制数字,其中就包含了你在计算机上输入的字符(文字)编码后的二进制数字。OK,正题开始,mysql字符处理流程: 首先,你要明白client输入的文字(字符)是以编码后的二进制数字在计算机内存中存在的,这个client环境是使用什么编码方式,是由你或系统所设置,并不受mysql影响。 输入完命令,回车后,client上的数据(二进制数字)通过TCP/IP协议管道传输到server。但是你要注意到,当前你client使用的编码方式可能与server上正在使用的不一样! character_set_client ,character_set_connection ,character_set_results都是设置编码方式,如gbk,utf8等等...

蛮大人123 2019-12-02 01:43:13 0 浏览量 回答数 0

问题

memcached的性能问题

huc_逆天 2020-05-28 09:16:56 1 浏览量 回答数 0

问题

memcached的性能问题:报错

kun坤 2020-06-05 23:58:24 0 浏览量 回答数 1

问题

memcached的性能问题 - memcached报错

montos 2020-05-29 23:51:30 0 浏览量 回答数 1

问题

为什么云服务器 ECS Linux 执行命令会导致实际执行的是历史命令

boxti 2019-12-01 22:05:32 1180 浏览量 回答数 0

回答

因为sprintf是不安全的,所以默认情况下编译器拒绝编译包含对它调用的代码。#define _CRT_SECURE_NO_WARNINGS 可以让编译器对此放行。什么叫不安全呢?我们知道,对于x86处理器来说,程序的数据和指令都是放在同一个内存中的,如果我们开辟的缓冲区比较小,而给sprintf传递了一个很大的字符串就会发生缓冲区溢出,这样可能破坏堆栈,如果堆栈中返回地址被修改,那么精心构造的攻击数据可能让程序转入另一个数据区域,并且将那里的数据当成代码执行。如果这些代码不怀好意,那么就会破坏你的电脑为所欲为,所以叫不安全。

a123456678 2019-12-02 02:15:43 0 浏览量 回答数 0

问题

设备可以收到平台下发的set指令 但是收不到get指令

specterking 2019-12-01 21:29:35 1265 浏览量 回答数 5

回答

ReLinuxBash严重漏洞修复紧急通知 看啥版本都不会啊,也不会怎么修复,有更详细的教程吗,真是连菜鸟都称不上 ------------------------- 回64楼quintus的帖子 是不是用Putty连接的,用户名我输入好后,密码输不进去呢, 打字符没反应的,只有回车会换行,图下 进去之后是不是输入指令就行了,还有我不知道我用的是什么版本,怎么查看啊,我是超级菜菜鸟,知道的告诉我下 ------------------------- 回132楼kingone的帖子 恩,我已经进去修复了,好像是修复好了的,但是不是要重启啊,我一重启就出现了这个,如下图 我重启的指令是shutdown -r now ,还用reboot,都提示这个错误,怎么破呢?大神回复下我这个菜鸟下吧

黑乎乎的 2019-12-02 00:31:57 0 浏览量 回答数 0

问题

Python基础测验(试题篇)

珍宝珠 2019-12-01 22:01:45 760 浏览量 回答数 2

问题

【精品问答】python技术1000问(1)

问问小秘 2019-12-01 21:57:48 454222 浏览量 回答数 19

问题

Python基础测验(答案篇)

珍宝珠 2019-12-01 22:02:53 603 浏览量 回答数 1

回答

首先,既然你要画残差(residual)的qqplot 那一定要先做回归。 你没说明回归自变量和因变量都是什么,假设第二列是因变量pressure[2],第三列是自变量pressure[3] 1.回归 >lm.fit<-lm(pressure[2]~1+pressure[3]) 2.做qq图 这里不用qqplot这个指令,用qqnorm和qqline就好 >qqnorm(lm.fit$res) >qqliine(lm.fit$res) 提取?就直接write.table() 比如你要第二列和第三列 >write.table(pressure[c(2,3)],file="c:\test.txt",quote=F,row.names=F,sep="\t") 第一个参数pressure[c(2,3)]是你要提取的变量 第二个参数file= 是你要存放的地址和文件名 第三个参数quote=F 是你打出来的数字都没有引号(默认是字符型) 第四个参数row.names=F 是不要行名称(为什么不要?自己试试就知道了) 第五个参数sep="\t" 每列数据之间空一个tab的距离,也就是8个字节,清晰明了。 答案来源于网络

养狐狸的猫 2019-12-02 02:41:11 0 浏览量 回答数 0

问题

【Java学习全家桶】1460道Java热门问题,阿里百位技术专家答疑解惑

管理贝贝 2019-12-01 20:07:15 27612 浏览量 回答数 19

回答

你可以做个简单的封装######觉得node官方没有用心做东西,做出来的库简直惨目忍睹######还有字符集转码的问题,只能通过第三方解决,而且windows下面用不了的######每种东西都有它专注的点!######有第三方的js吧!基于nodejs来的,比较好操作。######一个download过程从底层涉及到的过程工序有几百道,CPU指令可能有几千万条,涉及到各种硬件,软件,协议,路由,网关,数模转换等.所以针对各种层次的用户暴露出各种不同抽象的接口.当然最顶层就是url和savePath,很显然,nodeJs不是针对这层用户写的.######回复 @唐阳 : 绝得nodejs很好用的人######那什么人适合用node呢######nodeJs 就不是给普通网站开发人员用的######那我还不如用其他语言,干嘛用脚本啊######回复 @唐阳 : 偏底层和网络这块######额,那是给谁用的?######这就是nodejs的理念,什么都做了node.js的社区还会这么火吗?######额,不清楚######给js好的人用的,把js当做网页特效工具语言的“高级程序员”不一定能驾驭nodejs######nodeJS本来就是很底层的东西,这样灵活性更高。所以学习难度就大了,就像java和c一样,你能说c难用?只不过是java容易入门点而已。

kun坤 2020-06-09 11:13:48 0 浏览量 回答数 0

问题

C语言函数 【问答合集】

马铭芳 2019-12-01 20:09:44 1050 浏览量 回答数 1

回答

有必要; Redis事务使用总结: Redis的事务机制允许同时执行多条指令,它是原子性操作,事务中的命令要么全部执行,要么全部不执行,另外,事务中的所有指令都会被序列化,而且其开始执行过程中,不回被即时过来的指令所打断,其需要经历三个过程,分别为开始事务、命令入队以及执行事务。 · 相关命令 · 如何使用 · 脚本事务 · 遇到问题 · 例子演示 一、相关命令 1、MULTI 该命令用来开启事务,它总是返回ok结果,当其执行之后,客户端可以继续发送任意条数量的指令,这些指令不会立即被执行,而是被放到了队列中,直到EXEC被调用之后,所有命令才会被序列化执行。 2、EXEC 该命令负责触发并执行队列中所有的命令。 NOTE: 如果MULTI开启之后,因为某些原因没有成功执行EXEC,那么事务中所有的命令都不会被执行的。 3、DISCARD 该命令用来刷新事务中所有排队等待执行的指令,它总是返回ok结果,并且将服务连接状态恢复到正常。如果已经使用WATCH,那么其会将释放所有被WATCH的key。 4、WATCH 标记所有指定的key被监控起来,使其在事务中有条件的执行(乐观锁)。 NOTE: A、WATCH使得EXEC命令需要有条件的执行,也就是事务只能在所有被监视的键没有被修改的前提下才能执行。另外,在EXEC被执行之后,所有的WATCH都会被取消。 B、UNWATCH手动取消对所有键的WATCH,如果执行了EXEC或者DISCARD,则不需要手动执行UNWATCH命令。 二、如何使用 Redis原生使用(Redis-cli): 127.0.0.1:6379> multi // 事务开始的动作标志下面即为入队 OK 127.0.0.1:6379> set book-name "Thinking in Java" QUEUED 127.0.0.1:6379> get book-name QUEUED 127.0.0.1:6379> sadd tag "java" "Programming""Thinking" QUEUED 127.0.0.1:6379> smembers tag QUEUED 127.0.0.1:6379> exec // 执行事务 1) OK 2) "Thinking in Java" 3) (integer) 3 4) 1) "Thinking" 2) "Programming" 3) "java" 127.0.0.1:6379> discard // 事务已执行完毕 已经自动取消 (error) ERR DISCARD without MULTI 127.0.0.1:6379> multi OK 127.0.0.1:6379> set book-name "Patterns in Java" QUEUED 127.0.0.1:6379> get book-name QUEUED 127.0.0.1:6379> sadd tag "Java" "Thinking""Programming" QUEUED 127.0.0.1:6379> smembers tag QUEUED 127.0.0.1:6379> discard // 事务未执行 可以刷新队列指令状态 取消执行 OK 127.0.0.1:6379> exec // 事务已经被取消不能再执行 (error) ERR EXEC without MULTI 三、脚本事务 Redis 2.6开始支持了脚本,而该脚本本身就是一种事务机制,所以任何在事务里可以完成的事,在脚本里面也能完成,并且使用脚本更简单些,并且速度也更快。不过因为事务提供了一种即使不使用脚本,也可以避免竞争条件的方法,并且事务本身的实现并不复杂,所以现在的使用也比较多,但不排除日后可能被替代或是占据主要地位的可能。 NOTE: Redis为什么引入两种处理事务的方式?脚本功能是 Redis 2.6 才引入的,而事务功能则在更早之前就存在,所以 Redis 才会同时存在两种处理事务的方法。另外,事务脚本会在后续文章中总结介绍。 四、遇到问题 1、乐观锁实现 举个例子,假设我们需要原子性为某个键加1操作(假设INCR不存在),那么应该是这样的执行语句: SET mykey 1 val = GET mykey val = val + 1 SET mykey ${val} 单个客户端访问操作没有任何问题,如果是多个客户端同时访问mykey,就会产生资源共享访问问题,比如:现在有个两个客户端访问同一个键mykey,那么mykey的可能是2,但是我们期望的值应该是3才对,这个类似于高并发下的sync锁机制,所以我们需要使用WATCH来监控被共享的键mykey,如下: WATCH mykey(可监控多个键) val = GET mykey val = val + 1 MULTI SET mykey ${val} EXEC NOTE: 虽然大多情况下,多个客户端访问操作同一个键的情况很少或没有,但是不能排除这个特殊情况,所以建议在有可能产生键共享的指令中使用WATCH在EXEC执行前对其监管。 2、Redis不支持回滚(Roll Back) Redis的事务不支持回滚,这点不同于关系数据库中的事务,所以它的内部保持了简单且快速的特点。另外,Redis不支持回滚是这样考虑的:Redis事务中命令之所以会失败,是由于错误的编程所造成,通过事务回滚是不能回避这个根本问题。 NOTE: Redis事务中命令执行失败,仍会继续执行后面的执行,在没有特殊干预前提下,直到执行完队列中所有指令为止。 3、使用事务可能遇到的问题 A、事务在执行 EXEC 之前,入队的命令可能会出错,举个例子:命令可能会产生语法错误(参数数量错误,参数名错误等),或者其他更严重的错误,比如内存不足(如果服务器使用maxmemory 设置了最大内存限制的话)。 B、事务在执行 EXEC 之前,举个例子:事务中的命令可能处理了错误类型的键,比如将列表命令用在了字符串键上面等。 对于发生在 EXEC 执行之前的错误,客户端以前的做法是检查命令入队所得的返回值:如果命令入队时返回QUEUED ,那么入队成功;否则,就是入队失败。如果有命令在入队时失败,那么大部分客户端都会停止并取消这个事务。 从 Redis 2.6.5 开始,服务器会对命令入队失败的情况进行记录,并在客户端调用 EXEC 命令时,拒绝执行并自动放弃这个事务。 在 Redis 2.6.5 以前, Redis 只执行事务中那些入队成功的命令,而忽略那些入队失败的命令。而新的处理方式则使得在管道技术中包含事务变得简单,因为发送事务和读取事务的回复都只需要和服务器进行一次通讯即可。 至于那些在 EXEC 命令执行之后所产生的错误,并没有对它们进行特别处理: 即使事务中有某个/某些命令在执行时产生了错误, 事务中的其他命令仍然会继续执行。 五、例子演示 connect('127.0.0.1',6379); $result = array(); // 开启事务 $redis->multi(); // 添加指令到队列 $redis->set('book-name','Thinking in PHP!'); $redis->sAdd('tags','PHP','Programming','Thinking'); $bookname = $redis->get('book-name'); $tags = $redis->sMembers('tags'); // 执行事务 $redis->exec(); // 显示结果 echo '书名:'.$bookname.' 标签:'.$tags; ?> 结果: 答案来源于网络

问问小秘 2019-12-02 03:02:33 0 浏览量 回答数 0

回答

有必要; Redis事务使用总结: Redis的事务机制允许同时执行多条指令,它是原子性操作,事务中的命令要么全部执行,要么全部不执行,另外,事务中的所有指令都会被序列化,而且其开始执行过程中,不回被即时过来的指令所打断,其需要经历三个过程,分别为开始事务、命令入队以及执行事务。 ·     相关命令 ·     如何使用 ·     脚本事务 ·     遇到问题 ·     例子演示 一、相关命令 1、MULTI 该命令用来开启事务,它总是返回ok结果,当其执行之后,客户端可以继续发送任意条数量的指令,这些指令不会立即被执行,而是被放到了队列中,直到EXEC被调用之后,所有命令才会被序列化执行。 2、EXEC 该命令负责触发并执行队列中所有的命令。 NOTE: 如果MULTI开启之后,因为某些原因没有成功执行EXEC,那么事务中所有的命令都不会被执行的。 3、DISCARD 该命令用来刷新事务中所有排队等待执行的指令,它总是返回ok结果,并且将服务连接状态恢复到正常。如果已经使用WATCH,那么其会将释放所有被WATCH的key。 4、WATCH 标记所有指定的key被监控起来,使其在事务中有条件的执行(乐观锁)。 NOTE: A、WATCH使得EXEC命令需要有条件的执行,也就是事务只能在所有被监视的键没有被修改的前提下才能执行。另外,在EXEC被执行之后,所有的WATCH都会被取消。 B、UNWATCH手动取消对所有键的WATCH,如果执行了EXEC或者DISCARD,则不需要手动执行UNWATCH命令。 二、如何使用 Redis原生使用(Redis-cli): 127.0.0.1:6379> multi     // 事务开始的动作标志下面即为入队 OK 127.0.0.1:6379> set book-name "Thinking in Java" QUEUED 127.0.0.1:6379> get book-name QUEUED 127.0.0.1:6379> sadd tag "java" "Programming""Thinking" QUEUED 127.0.0.1:6379> smembers tag QUEUED 127.0.0.1:6379> exec     // 执行事务 1) OK 2) "Thinking in Java" 3) (integer) 3 4) 1) "Thinking" 2) "Programming" 3) "java" 127.0.0.1:6379> discard  // 事务已执行完毕 已经自动取消 (error) ERR DISCARD without MULTI 127.0.0.1:6379> multi OK 127.0.0.1:6379> set book-name "Patterns in Java" QUEUED 127.0.0.1:6379> get book-name QUEUED 127.0.0.1:6379> sadd tag "Java" "Thinking""Programming" QUEUED 127.0.0.1:6379> smembers tag QUEUED 127.0.0.1:6379> discard  // 事务未执行 可以刷新队列指令状态 取消执行 OK 127.0.0.1:6379> exec     // 事务已经被取消不能再执行 (error) ERR EXEC without MULTI 三、脚本事务 Redis 2.6开始支持了脚本,而该脚本本身就是一种事务机制,所以任何在事务里可以完成的事,在脚本里面也能完成,并且使用脚本更简单些,并且速度也更快。不过因为事务提供了一种即使不使用脚本,也可以避免竞争条件的方法,并且事务本身的实现并不复杂,所以现在的使用也比较多,但不排除日后可能被替代或是占据主要地位的可能。 NOTE: Redis为什么引入两种处理事务的方式?脚本功能是 Redis 2.6 才引入的,而事务功能则在更早之前就存在,所以 Redis 才会同时存在两种处理事务的方法。另外,事务脚本会在后续文章中总结介绍。 四、遇到问题 1、乐观锁实现 举个例子,假设我们需要原子性为某个键加1操作(假设INCR不存在),那么应该是这样的执行语句: SET mykey 1 val = GET mykey val = val + 1 SET mykey ${val} 单个客户端访问操作没有任何问题,如果是多个客户端同时访问mykey,就会产生资源共享访问问题,比如:现在有个两个客户端访问同一个键mykey,那么mykey的可能是2,但是我们期望的值应该是3才对,这个类似于高并发下的sync锁机制,所以我们需要使用WATCH来监控被共享的键mykey,如下: WATCH mykey(可监控多个键) val = GET mykey val = val + 1 MULTI SET mykey ${val} EXEC NOTE: 虽然大多情况下,多个客户端访问操作同一个键的情况很少或没有,但是不能排除这个特殊情况,所以建议在有可能产生键共享的指令中使用WATCH在EXEC执行前对其监管。 2、Redis不支持回滚(Roll Back) Redis的事务不支持回滚,这点不同于关系数据库中的事务,所以它的内部保持了简单且快速的特点。另外,Redis不支持回滚是这样考虑的:Redis事务中命令之所以会失败,是由于错误的编程所造成,通过事务回滚是不能回避这个根本问题。 NOTE: Redis事务中命令执行失败,仍会继续执行后面的执行,在没有特殊干预前提下,直到执行完队列中所有指令为止。 3、使用事务可能遇到的问题 A、事务在执行 EXEC 之前,入队的命令可能会出错,举个例子:命令可能会产生语法错误(参数数量错误,参数名错误等),或者其他更严重的错误,比如内存不足(如果服务器使用maxmemory 设置了最大内存限制的话)。 B、事务在执行 EXEC 之前,举个例子:事务中的命令可能处理了错误类型的键,比如将列表命令用在了字符串键上面等。 对于发生在 EXEC 执行之前的错误,客户端以前的做法是检查命令入队所得的返回值:如果命令入队时返回QUEUED ,那么入队成功;否则,就是入队失败。如果有命令在入队时失败,那么大部分客户端都会停止并取消这个事务。 从 Redis 2.6.5 开始,服务器会对命令入队失败的情况进行记录,并在客户端调用 EXEC 命令时,拒绝执行并自动放弃这个事务。 在 Redis 2.6.5 以前, Redis 只执行事务中那些入队成功的命令,而忽略那些入队失败的命令。而新的处理方式则使得在管道技术中包含事务变得简单,因为发送事务和读取事务的回复都只需要和服务器进行一次通讯即可。 至于那些在 EXEC 命令执行之后所产生的错误,并没有对它们进行特别处理: 即使事务中有某个/某些命令在执行时产生了错误, 事务中的其他命令仍然会继续执行。 五、例子演示 <?php $redis = new \Redis(); $redis->connect('127.0.0.1',6379); $result = array(); // 开启事务 $redis->multi(); // 添加指令到队列 $redis->set('book-name','Thinking in PHP!'); $redis->sAdd('tags','PHP','Programming','Thinking'); $bookname = $redis->get('book-name'); $tags = $redis->sMembers('tags'); // 执行事务 $redis->exec(); // 显示结果 echo '书名:'.$bookname.' 标签:'.$tags; ?> 结果:   答案来源于网络

养狐狸的猫 2019-12-02 02:14:26 0 浏览量 回答数 0

回答

一个函数的调用开销抵得上上千个CPU指令周期!! 我们写普通应用时应该以可读性为主,仅在必要的时候才进行性能优化。但这种非常low-level的代码必须严格对待效率问题。所以这个问题用宏来实现是最好的方式。 相比if语句,用宏+查表法实现可能第一次执行会比if语句慢,因为要把整张表加载到高速缓存,但之后的每一次调用都将比if语句快,更比函数方式快N倍。 补充回答 首先,“查表查表”,指的是什么样的一张表呢?是这么一张表: static const short ctype_tab[257] = { 0, / EOF / _BB, _BB, _BB, _BB, _BB, _BB, _BB, _BB, _BB, _CN, _CN, _CN, _CN, _CN, _BB, _BB, _BB, _BB, _BB, _BB, _BB, _BB, _BB, _BB, _BB, _BB, _BB, _BB, _BB, _BB, _BB, _BB, _SP, _PU, _PU, _PU, _PU, _PU, _PU, _PU, _PU, _PU, _PU, _PU, _PU, _PU, _PU, _PU, XDI, XDI, XDI, XDI, XDI, XDI, XDI, XDI, XDI, XDI, _PU, _PU, _PU, _PU, _PU, _PU, _PU, XUP, XUP, XUP, XUP, XUP, XUP, _UP, _UP, _UP, _UP, _UP, _UP, _UP, _UP, _UP, _UP, _UP, _UP, _UP, _UP, _UP, _UP, _UP, _UP, _UP, _UP, _PU, _PU, _PU, _PU, _PU, _PU, XLO, XLO, XLO, XLO, XLO, XLO, _LO, _LO, _LO, _LO, _LO, _LO, _LO, _LO, _LO, _LO, _LO, _LO, _LO, _LO, _LO, _LO, _LO, _LO, _LO, _LO, _PU, _PU, _PU, _PU, _BB, };此数组长度257,实际只初始化了前面129个元素。但是实际用来判断的_Ctype是截取了该数组的后面256个元素: const short *_Ctype = &ctype_tab[1];忽略掉那个EOF的0,注意看上面的128个元素。这实际上是对整个ASCII表进行了归类。比如_LO表示小写字母,_UP表示大写字母,_DI表示数字,这些宏常量都已经在前面定义了的。注意对于数字,他并不是用的_DI,而是XDI,这代表这些数字同时代表十进制数字+十六进制数字,同理,字母中的A-F和a-f也不是_UP或_LO而是XUP和XLO,表示它们即是字母又是十六进制数字。 这样分类之后,它又是怎么判断一个字符的属性的呢?主要的技巧是每个类别的常量之间是互斥的,把它们的值转成二进制以后,每个常量的1的位置是不同的。例如_LO的值是0x10,二进制是1 0000,1在右数第五位,而其他的几个常量中的1全部与它不同,不信你可以自己验证一下(几个组合常量除外)。 实际上,它是从_XD(代表十六进制数字的常量)到_XA(代表编码超过128的那些ASCII超集字符),每个常量都是前一个的2倍。2倍在二进制中相当于把1向左挪动了一位,这样每一个常量中的1就错开了。 这种技巧在编程中有一个专门的名字:掩码,英文名字是Mask,它除了可以判断一个值是不是某个我期望的值之外,还能很容易地进行组合判断。比如g是小写字母,而a不仅是小写字母,还是一个十六进制数字。 判断的时候,只要把实际值与预先定义的掩码进行与操作,然后判断结果是否不为0即可。 例如,你拿到一个小写字母g,它在该表中对应的值是_LO即0x10,二进制为1 0000,(请自行对照着ASCII码表来看),此时把它与_LO相与,即10000 & 10000,由于第五位都是1,所以结果不为0,表示它是一个小写字母。 如果你拿到的不是一个小写字母,例如是大写字母G,它在该表中对应的值是_UP即0x02(二进制10),此时把它与_LO相与,即10 & 10000,结果为0,表示它不是一个小写字母。其他同理。 如果你拿到一个具有组合属性的字符,例如a,它在表中对应的值是XLO,这是一个由_XD和_LO进行或操作得到的组合值,即10 | 10000,得到的结果为10010,也就是十六进制的0x12。多个掩码之间进行或操作就相当于为它们赋予了多重属性,因为它们的二进制上有多个位置同时为1,这样它们就可以在多种判断中返回不为0的结果。以a为例,它与_LO进行与操作时结果不为0,表示它是一个小写字母,同时它与_XD进行与操作时结果也不为0,因此它也是一个十六进制数字。 基本原理就是这样。掩码其实很常见,比如对IP地址的网段的判断(子网掩码)、Windows的GDI编程中为画刷设置属性、某些系统中对角色权限的判断,等等。 最后,对于你的为什么要使用十六进制来定义的疑惑,实际上是为了清晰,一看就知道这些定义的是掩码。如果用二进制则太长,用十进制则不够直观(别忘了我们是程序员,天生对十六进制更加敏感)。

a123456678 2019-12-02 02:41:25 0 浏览量 回答数 0

回答

在Java中,常量池的概念想必很多人都听说过。这也是面试中比较常考的题目之一。在Java有关的面试题中,一般习惯通过String的有关问题来考察面试者对于常量池的知识的理解,几道简单的String面试题难倒了无数的开发者。所以说,常量池是Java体系中一个非常重要的概念。 谈到常量池,在Java体系中,共用三种常量池。分别是字符串常量池、Class常量池和运行时常量池。 本文先来介绍一下到底什么是Class常量池。 什么是Class文件 在Java代码的编译与反编译那些事儿中我们介绍过Java的编译和反编译的概念。我们知道,计算机只认识0和1,所以程序员写的代码都需要经过编译成0和1构成的二进制格式才能够让计算机运行。 我们在《深入分析Java的编译原理》中提到过,为了让Java语言具有良好的跨平台能力,Java独具匠心的提供了一种可以在所有平台上都能使用的一种中间代码——字节码(ByteCode)。 有了字节码,无论是哪种平台(如Windows、Linux等),只要安装了虚拟机,都可以直接运行字节码。 同样,有了字节码,也解除了Java虚拟机和Java语言之间的耦合。这话可能很多人不理解,Java虚拟机不就是运行Java语言的么?这种解耦指的是什么? 其实,目前Java虚拟机已经可以支持很多除Java语言以外的语言了,如Groovy、JRuby、Jython、Scala等。之所以可以支持,就是因为这些语言也可以被编译成字节码。而虚拟机并不关心字节码是有哪种语言编译而来的。 Java语言中负责编译出字节码的编译器是一个命令是javac。 javac是收录于JDK中的Java语言编译器。该工具可以将后缀名为.java的源文件编译为后缀名为.class的可以运行于Java虚拟机的字节码。 如,我们有以下简单的HelloWorld.java代码: public class HelloWorld { public static void main(String[] args) { String s = "Hollis"; } } 通过javac命令生成class文件: javac HelloWorld.java 生成HelloWorld.class文件:  如何使用16进制打开class文件:使用 vim test.class ,然后在交互模式下,输入:%!xxd 即可。 可以看到,上面的文件就是Class文件,Class文件中包含了Java虚拟机指令集和符号表以及若干其他辅助信息。 要想能够读懂上面的字节码,需要了解Class类文件的结构,由于这不是本文的重点,这里就不展开说明了。 读者可以看到,HelloWorld.class文件中的前八个字母是cafe babe,这就是Class文件的魔数(Java中的”魔数”) 我们需要知道的是,在Class文件的4个字节的魔数后面的分别是4个字节的Class文件的版本号(第5、6个字节是次版本号,第7、8个字节是主版本号,我生成的Class文件的版本号是52,这时Java 8对应的版本。也就是说,这个版本的字节码,在JDK 1.8以下的版本中无法运行)在版本号后面的,就是Class常量池入口了。 Class常量池 Class常量池可以理解为是Class文件中的资源仓库。 Class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池(constant pool table),用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References)。 由于不同的Class文件中包含的常量的个数是不固定的,所以在Class文件的常量池入口处会设置两个字节的常量池容量计数器,记录了常量池中常量的个数。  当然,还有一种比较简单的查看Class文件中常量池的方法,那就是通过javap命令。对于以上的HelloWorld.class,可以通过 javap -v HelloWorld.class 查看常量池内容如下:  从上图中可以看到,反编译后的class文件常量池中共有16个常量。而Class文件中常量计数器的数值是0011,将该16进制数字转换成10进制的结果是17。 原因是与Java的语言习惯不同,常量池计数器是从0开始而不是从1开始的,常量池的个数是10进制的17,这就代表了其中有16个常量,索引值范围为1-16。 常量池中有什么 介绍完了什么是Class常量池以及如何查看常量池,那么接下来我们就要深入分析一下,Class常量池中都有哪些内容。 常量池中主要存放两大类常量:字面量(literal)和符号引用(symbolic references)。 字面量 前面说过,运行时常量池中主要保存的是字面量和符号引用,那么到底什么字面量? 在计算机科学中,字面量(literal)是用于表达源代码中一个固定值的表示法(notation)。几乎所有计算机编程语言都具有对基本值的字面量表示,诸如:整数、浮点数以及字符串;而有很多也对布尔类型和字符类型的值也支持字面量表示;还有一些甚至对枚举类型的元素以及像数组、记录和对象等复合类型的值也支持字面量表示法。 以上是关于计算机科学中关于字面量的解释,并不是很容易理解。说简单点,字面量就是指由字母、数字等构成的字符串或者数值。 字面量只可以右值出现,所谓右值是指等号右边的值,如:int a=123这里的a为左值,123为右值。在这个例子中123就是字面量。 int a = 123; String s = "hollis"; 上面的代码事例中,123和hollis都是字面量。 本文开头的HelloWorld代码中,Hollis就是一个字面量。 符号引用 常量池中,除了字面量以外,还有符号引用,那么到底什么是符号引用呢。 符号引用是编译原理中的概念,是相对于直接引用来说的。主要包括了以下三类常量: * 类和接口的全限定名 * 字段的名称和描述符 * 方法的名称和描述符 这也就可以印证前面的常量池中还包含一些com/hollis/HelloWorld、main、([Ljava/lang/String;)V等常量的原因了。 Class常量池有什么用 前面介绍了这么多,关于Class常量池是什么,怎么查看Class常量池以及Class常量池中保存了哪些东西。有一个关键的问题没有讲,那就是Class常量池到底有什么用。 首先,可以明确的是,Class常量池是Class文件中的资源仓库,其中保存了各种常量。而这些常量都是开发者定义出来,需要在程序的运行期使用的。 在《深入理解Java虚拟》中有这样的表述: Java代码在进行Javac编译的时候,并不像C和C++那样有“连接”这一步骤,而是在虚拟机加载Class文件的时候进行动态连接。也就是说,在Class文件中不会保存各个方法、字段的最终内存布局信息,因此这些字段、方法的符号引用不经过运行期转换的话无法得到真正的内存入口地址,也就无法直接被虚拟机使用。当虚拟机运行时,需要从常量池获得对应的符号引用,再在类创建时或运行时解析、翻译到具体的内存地址之中。关于类的创建和动态连接的内容,在虚拟机类加载过程时再进行详细讲解。 前面这段话,看起来很绕,不是很容易理解。其实他的意思就是: Class是用来保存常量的一个媒介场所,并且是一个中间场所。在JVM真的运行时,需要把常量池中的常量加载到内存中。 至于到底哪个阶段会做这件事情,以及Class常量池中的常量会以何种方式被加载到具体什么地方,会在本系列文章的后续内容中继续阐述。欢迎关注我的博客(http://www.hollischuang.com) 和公众号(Hollis),即可第一时间获得最新内容。 另外,关于常量池中常量的存储形式,以及数据类型的表示方法本文中并未涉及,并不是说这部分知识点不重要,只是Class字节码的分析本就枯燥,作者不想在一篇文章中给读者灌输太多的理论上的内容。感兴趣的读者可以自行Google学习,如果真的有必要,我也可以单独写一篇文章再深入介绍。 参考资料 《深入理解java虚拟机》 《Java虚拟机原理图解》 1.2.2、Class文件中的常量池详解(上)

montos 2020-06-02 10:12:18 0 浏览量 回答数 0

回答

一。zval、引用计数、变量分离、写时拷贝我们一步步来理解1、php语言特性PHP是脚本语言,所谓脚本语言,就是说PHP并不是独立运行的,要运行PHP代码需要PHP解析器,用户编写的PHP代码最终都会被PHP解析器解析执行PHP的执行是通过Zend engine(ZE, Zend引擎),ZE是用C编写的用户编写的PHP代码最终都会被翻译成PHP的虚拟机ZE的虚拟指令(OPCODES)来执行也就说最终会被翻译成一条条的指令既然这样,有什么结果和你预想的不一样,查看php源码是最直接最有效的 2、php变量的存储结构在PHP中,所有的变量都是用一个结构zval结构来保存的,在Zend/zend.h中可以看到zval的定义:zval结构包括:① value —— 值,是真正保存数据的关键部分,定义为一个联合体(union)② type —— 用来储存变量的类型 ③ is_ref —— 下面介绍④ refcount —— 下面介绍 声明一个变量$addr="北京";PHP内部都是使用zval来表示变量的,那对于上面的脚本,ZE是如何把addr和内部的zval结构联系起来的呢?变量都是有名字的(本例中变量名为addr)而zval中并没有相应的字段来体现变量名。PHP内部肯定有一个机制,来实现变量名到zval的映射在PHP中,所有的变量都会存储在一个数组中(确切的说是hash table)当你创建一个变量的时候,PHP会为这个变量分配一个zval,填入相应的信息,然后将这个变量的名字和指向这个zval的指针填入一个数组中。当你获取这个变量的时候,PHP会通过查找这个数组,取得对应的zval 注意:数组和对象这类复合类型在生成zval时,会为每个单元生成一个zval3、我们经常说每个变量都有一个内存地址,那这个zval和变量的内存地址,这俩有什么关系吗?定义一个变量会开辟一块内存,这块内存好比一个盒子,盒子里放了zval,zval里保存了变量的相关信息,需要开辟多大的内存,是由zval所占空间大小决定的zval是内存对象,垃圾回收的时候会把zval和内存地址(盒子)分别释放掉 4、引用计数、变量分离、写时拷贝zval中的refcount和is_ref还没有介绍,我们知道PHP是一个长时间运行的服务器端脚本。那么对于它来说,效率和资源占用率是一个很重要的衡量标准,也就是说,PHP必须尽量减少内存占用率。考虑下面这段代码:第一行代码创建了一个字符串变量,申请了一个大小为9字节的内存,保存了字符串“laruence”和一个NULL(0)的结尾第二行定义了一个新的字符串变量,并将变量var的值“复制”给这个新的变量第三行unset了变量var 这样的代码是很常见的,如果PHP对于每一个变量赋值都重新分配内存,copy数据的话,那么上面的这段代码就要申请18个字节的内存空间,为了申请新的内存,还需要cpu执行某些计算,这当然会加重cpu的负载而我们也很容易看出来,上面的代码其实根本没有必要申请两份空间,当第三句执行后,$var被释放了,我们刚才的设想(申请18个字节内存空间)突然变的很滑稽,这次复制显得好多余。如果早知道$var不用了,直接让$var_dup用$var的内存不就行了,还复制干嘛?如果你觉得9个字节没什么,那设想下如果$var是个10M的文件内容,或者20M,是不是我们的计算机资源消耗的有点冤枉呢?呵呵,PHP的开发者也看出来了: 刚才说了,PHP中的变量是用一个存储在symbol_table中的符号名,对应一个zval来实现的,比如对于上面的第一行代码,会在symbol_table中存储一个值“var”,对应的有一个指针指向一个zval结构,变量值“laruence”保存在这个zval中,所以不难想象,对于上面的代码来说,我们完全可以让“var”和“var_dup”对应的指针都指向同一个zval就可以了(额,鸟哥一会说hash table,一会说symbol_table,暂且理解为symbol_table是hash table的子集) PHP也是这样做的,这个时候就需要介绍一下zval结构中的refcount字段了refcount,引用计数,记录了当前的zval被引用的次数(这里的引用并不是真正的 & ,而是有几个变量指向它)比如对于代码:第一行,创建了一个整形变量,变量值是1。 此时保存整形1的这个zval的refcount为1第二行,创建了一个新的整形变量(通过赋值的方式),变量也指向刚才创建的zval,并将这个zval的refcount加1,此时这个zval的refcount为2所以,这个时候(通过值传递的方式赋值给别的变量),并没有产生新的zval,两个变量指向同一zval,通过一个计数器来共用zval及内存地址,以达到节省内存空间的目的当一个变量被第一次创建的时候,它对应的zval结构的refcount的值会被初始化为1,因为只有这一个变量在用它。但是当你把这个变量赋值给别的变量时,refcount属性便会加1变成2,因为现在有两个变量在用这个zval结构了 PHP提供了一个函数可以帮助我们了解这个过程debug_zval_dump输出:long(1) refcount(2)long(1) refcount(3)如果你奇怪 ,var的refcount应该是1啊?我们知道,对于简单变量,PHP是以传值的形式传参数的。也就是说,当执行debug_zval_dump($var)的时候,$var会以传值的方式传递给debug_zval_dump,也就是会导致var的refcount加1,所以只要能看到,当变量赋值给一个变量以后,能导致zval的refcount加1这个结果即可现在我们回头看上面的代码, 当执行了最后一行unset($var)以后,会发生什么呢?unset($var)的时候,它删除符号表里的$var的信息,准备清理它对应的zval及内存空间,这时它发现$var对应的zval结构的refcount值是2,也就是说,还有另外一个变量在一起用着这个zval,所以unset只需把这个zval的refcount减去1就行了上代码:输出:string(8) "laruence" refcount(2) 但是,对于下面的代码呢?很明显在这段代码执行以后,$var_dup的值应该还是“laruence”,那么这又是怎么实现的呢?这就是PHP的copy on write机制(简称COW):PHP在修改一个变量以前,会首先查看这个变量的refcount,如果refcount大于1,PHP就会执行一个分离的过程(在Zend引擎中,分离是破坏一个引用对的过程)对于上面的代码,当执行到第三行的时候,PHP发现$var想要改变,并且它指向的zval的refcount大于1,那么PHP就会复制一个新的zval出来,改变其值,将改变的变量指向新的zval(哪个变量指向新复制的zval其实已经无所谓了),并将原zval的refcount减1,并修改symbol_table里该变量的指针,使得$var和$var_dup分离(Separation)。这个机制就是所谓的copy on write(写时复制,这里的写包括普通变量的修改及数组对象里的增加、删除单元操作)如果了解了is_ref之后,上面说的并不严谨 上代码测试:输出:long(1) refcount(2)string(8) "laruence" refcount(2) 现在我们知道,当使用变量复制的时候 ,PHP内部并不是真正的复制,而是采用指向相同的zval结构来节约开销。那么,对于PHP中的引用,又是如何实现呢?这段代码结束以后,$var也会被间接的修改为1,这个过程称作(change on write:写时改变)那么ZE是怎么知道,这次的复制不需要Separation呢?这个时候就要用到zval中的is_ref字段了:对于上面的代码,当第二行执行以后,$var所代表的zval的refcount变为2,并且设置is_ref为1到第三行的时候,PHP先检查var_ref对应的zval的is_ref字段(is_ref 表示该zval是否被&引用,仅表示真或假,就像开关的开与关一样,zval的初始化情况下为0,即非引用),如果为1,则不分离,直接更改(否则需要执行刚刚提到的zval分离),更改共享的zval实际上也间接更改了$var的值,因为引擎想所有的引用变量都看到这一改变php源码做了这样一个判断,大体逻辑示意如下:如果这个zval中的if_ref为1(即被引用),或者该zval引用计数小于2任何一种方式:都不会进行分离 尽管已经存在写时复制和写时改变,但仍然还存在一些不能通过is_ref和refcount来解决的问题对于如下的代码,又会怎样呢?这里$var、$var_dup、$var_ref三个变量将共用一个zval结构(其实这是不可能的,一个zval不可能既被&,又被指向),有两个属于change-on-write组合($var和$var_ref),有两个属于copy-on-write组合($var和$var_dup),那is_ref和refcount该怎样工作,才能正确的处理好这段复杂的关系呢?答案是不可能!在这种情况下,变量的值必须分离成两份完全独立的存在当执行第二行代码的时候,和前面讲过的一样,$var_dup 和 $var 指向相同的zval, refcount为2当执行第三行的时候,PHP发现要操作的zval的refcount大于1,则PHP会执行Separation(也就是说php将一个zval的is_ref从0设为1 之前,当然此时refcount还没有增加,会看该zval的refcount,如果refcount>1,则会分离), 将$var_dup分离出去,并将$var和$var_ref做change on write关联。也就是,refcount=2, is_ref=1;所以内存会给变量var_dup 分配出一个新的zval,类型与值同 $var和$var_ref指向的zval一样,是新分配出来的,尽管他们拥有同样的值,但是必须通过两个zval来实现。试想一下,如果三者指向同一个zval的话,改边 $var_dup 的值,那么 $var和$var_ref 也会受到影响,这样就乱套了图解:下面的这段代码在内核中同样会产生歧义,所以需要强制复制!也就是说一个zval不会既被引用,又被指向,必须分离 基于这样的分析,我们就可以让debug_zval_dump出refcount为1的结果来:输出:string(8) "laruence" refcount(1) 为什么结果是refcount(1)呢debug_zval_dump()中参数是引用的话,refcount永远为1这两段代码在执行的时候是这样的逻辑:PHP先看变量指向的zval是否被引用,如果是引用,则不再产生新的zval甭管哪个变量引用了它,比如有个变量$a被引用了,$b=&$a,就算自己引用自己$a=&$a,$a所指向的zval都不会被复制,改变其中一个变量的值,另一个值也被改变(写时改变)如果is_ref为0且refcount大于1,改变其中一个变量时,复制新的zval(写时复制) 还有一个知识点需要了解下,就是PHP数组复制的机制复制一个数组,就是把一个数组赋值给一个变量便可。会把数组指针位置一同复制。这里面有两种情况:① 指针位置合法,这时直接复制,无影响② 原数组指针位置非法时(移出界),“新”数组指针会初始化(这里的新为什么要加引号?请看下文),而老的数组指针位置不变,还是false先看例子: 结果:!结果:出现这种情况好像不对?$arr2 难道不是新数组?新数组的数组指针应该重置了啊这里注意了:$arr2 = $arr1 ,在俩变量都没发生写操作时,他们其实引用的是同一个内存地址。在其中一个变量发生写操作后,内存地址会复制一份,发生改变的变量会去引用它,并把数组指针初始化。所以 $arr1 会去引用复制的内存地址,并将指针初始化二。.foreach循环时调用current等函数!结果: 56按照之前说的,foreach先赋值,再移动指针,再执行循环体,第一次结果为2可以理解为什么三次都是2呢?咋就这么2呢?因为current函数是按引用传递的函数 在zval笔记中说了,一个zval不能既被引用,又被指向所以,变量分离,重新拷贝一份数组专门用于current函数 当然,如果数组zval的is_ref为1,则不会拷贝数组了或者:结果:current是引用传参

杨冬芳 2019-12-02 02:26:33 0 浏览量 回答数 0

问题

【精品问答】Python面试题汇总130问(框架篇)

珍宝珠 2019-12-01 22:04:22 1524 浏览量 回答数 0

回答

点击后disabled掉,回调回来再重置回来######前端不限制?######我觉得这个还是前端做限制会比较合适,如果后端的 话  我暂时想到的就是ip过滤  每个IP在指定的时间内只能访问几次    不过感觉这样有点浪费资源###### 需要前后端一起限制 1.前端限制,点击后disabled掉,回调回来或者超时再重置回来 2.后端,限制用户只能在一定时间内访问该接口一次,可以借助redis的字符串的类型的SETNX 命令。 请求进入在redis中计数,后续请求直接返回,查询redis有值就返回失败,处理完毕删除redis的值 ######这个怎么限制在一定时间内哪?######你的问题有两种理解方式 第一种:用户点击N次 然后后台排队按照点击次数,一次一次的执行;第二种:用户点击n次,只执行第一次点击,其余的都不执行; 如果是第二种:你只需要在后台设置一个变量 用这个值做判断就行了  后台在执行点击指令时 把他的值修改  防止第二次点击命令进来,然后执行完成后将值恢复。至于第一种 我对java没什么了解 但是我觉得应该可以利用类似列队的方式来解决######1.后台加锁机制 2.点击之后设置为disable,等到请求结束返回信息再设置为disable, ######后端可以编码限定请求频率,例如Guava的RateLimiter。或者通过Ngnix限制###### 加一个过滤器,每次请求到的时候给 session 里面设置一个时间戳,返回的时候 removeSession 中这个值,如果第二个请求来了判断 session 里面时间戳是否满足了时间间隔,如果不满足,就直接返回一个提示,提交太频繁 ######刚看是 app,这样的话就直接记录针对设备或账号设置一个最后请求的时间戳,然后对比,一样的道理,完全可以放内存里面,每次只为一个账号保留一个时间戳就行了,也用不了多大内存######我遇到这种问题都是最简单的方法, 存session个值, 当然一个用户换个浏览器就不好用了, 或者缓存 用户名和状态, 主要还是要前台限制, 如果是定时操作, 可以用settimeout代替用户操作######突然想到  每次请求返回一个只能使用一次的随机值  处理请求前先比对该值  不知道行不行

kun坤 2020-05-30 17:26:57 0 浏览量 回答数 0

回答

一般都是调用现成的命令,解析命令输出######回复 @Hyacinthus_M : 几乎所有编程语言都有执行命令获取输出的方法的,获取完之后,按行正则表达式匹配提取信息即可######回复 @Mallon : 那你能给点这方面解析的资料吗?我的GREP等用得不好,首先得有思路了,不然我会觉得还没有改代码来得可行。######回复 @Mallon : 意思是先iwlist eth0 scan | grep "Target"吗,那怎么样设置密码呢?在这方面我很迷惑######回复 @Hyacinthus_M : 你在程序里调用命令行,Linux下基本就是这个套路######可是要求是写程序。 这个程序是面对客户的,我总不能要求客户还能用命令行吧。我只想知道有没有代码量小点的方法。###### 是这样的。我开始的时候也想过通过用system调用通过shell的工具来完成任务,可是shell功底有些不足。 我所需要的只是iwlist eth0 scan 结果中的ESSID, TXPOWER,还有就是加密相关的内容。 而又要求将这些内容以每个网络块的方式输出,而通过grep 后,所有的相同的项都在一起了。 那么要通过样才能实现我的需求呢,shell我真的很基本。 ###### 引用来自“Hyacinthus_M”的答案 是这样的。我开始的时候也想过通过用system调用通过shell的工具来完成任务,可是shell功底有些不足。 我所需要的只是iwlist eth0 scan 结果中的ESSID, TXPOWER,还有就是加密相关的内容。 而又要求将这些内容以每个网络块的方式输出,而通过grep 后,所有的相同的项都在一起了。 那么要通过样才能实现我的需求呢,shell我真的很基本。 shell作为程序设计语言功能太弱了,上perl python吧,推荐后者,呵呵 ######回复 @Hyacinthus_M : 纯C麻烦,我没研究过...######这个程序只能C做,纯的。python,呵呵。说重点好吗,######grep是shell用的,其它语言都内置正则模块的###### http://stackoverflow.com/questions/646241/c-run-a-system-command-and-get-output######大哥,你没有把握我的意思啊。###### 正则就用PCRE吧 http://www.pcre.org/ ###### 按照楼主的描述,我猜公司是让你在一个嵌入式设备上实现该功能吧。 wireless-tools需要跟底层的硬件配合使用,它本身无非就是通过socket从内核获取到信息。设备的wifi驱动也是你们自己搞的?如果从驱动着手的话,可能还更简单点。方便的话,可以说一下你们所使用的平台。 ######我也是刚去上班不久的,对硬件了解也少,驱动好像不是他们写的。 我已经改了不少了,这个星期应该能完成吧。 iw_get_ext()这个接口?######是用的baspberrypi的。系统基本和debian的一样。只是只有基本的一些功能。######回复 @txgcwm : 大哥。真是谢谢你啊。 我真的很需要这样的交流。 你也早点睡啊。我先睡了。######回复 @Hyacinthus_M : 大哥。真是谢谢你啊。 我真的很需要这样的交流。 你也早点睡啊。我先睡了。######回复 @txgcwm : 你好。我对你说的“楼主可以使用fopen来执行“iwlist eth0 scan”指令,将获取到的结果逐个解析出来”的意思不是太理解? 是先将结果定向到一个文件中,然后再解析? 好像你不是这个意思啊,有些地方我不是很懂,可以请你说具体点吗######回复 @txgcwm : 是啊,我也想通过调用system()来运行iwlist eth0 scan来做,然后解析输出,包括无线网络的配置,同样也可以用同样的方法来做,但是我的问题出在解析部分。 希望你给点具体点的建议。######如果是那样的话,预计你执行那些指令是没有多少问题的。 楼主可以使用fopen来执行“iwlist eth0 scan”指令,将获取到的结果逐个解析出来(这样比你修改代码好多了,字符串解析应该相对简单一些嘛)。###### 引用来自“txgcwm”的答案 按照楼主的描述,我猜公司是让你在一个嵌入式设备上实现该功能吧。 wireless-tools需要跟底层的硬件配合使用,它本身无非就是通过socket从内核获取到信息。设备的wifi驱动也是你们自己搞的?如果从驱动着手的话,可能还更简单点。方便的话,可以说一下你们所使用的平台。 是的呢。我不是科班出身的,一直在自己摸索,有很多东西都不太懂,很多时候都是在用笨方法来解决。      开始的时候,我的确是想用SHELL来实现的,然后解析。但是我的头说要用程序写, 开始真是一点头绪都没有,我只能想到去修改wireless-tools的源程序了。 我觉得自己可以解决的。 不过,还是希望你能给点建议。 ######楼主,现在这个问题肯定解决了吧!能不能分享一下最后的结果啊?我现在也遇到了和你同样的问题,可是我没有楼主那么厉害,可以直接更改源代码。能不能帮一下小弟,谢谢先!!!######回复 @txgcwm : 你好,我已经使用解析的方法完成了基本功能。最近在使用基于wireless.h,iwlib.h iwlib.c三个文件(丢弃iwlist.c iwconfig.c)来重写该程序,在main.c中,包括了#include "iwlib.h", 并且在iwlib.h声明了所有的函数原型,所有的函数实现均在iwlib.c中,######回复 @txgcwm : 恩。我已经在baspberrypi的板子上运行过wireless-tools的工具了,iwlist scan结果正常。######回复 @txgcwm : 比如,把scan的结果定向到一个文件中,然后再通过字符串的操作来实现,还是scan | grep 的方法来实现呢? 后者我不太熟悉,我的功底还没能满足需求,但是前者,对多个关健字的解析方面的算法实现,思路不是很明确。######回复 @Hyacinthus_M : 而且我建议你将这个工具在没有修改前先编译进去,看看是否能够输出你想要的数据(没有的话可能底层不支持,那样的话你上层改了也没有用)。###### #include <sys/wait.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <stdio.h> #define MAXLINE 1024 int main(int argc, char **argv) { char buf[MAXLINE]; int rc = 0; FILE *fp = NULL; fp = popen("iwlist wlan0 scan", "r"); if(fp == NULL) { perror("popen error!"); return -1; } while(fgets(buf, MAXLINE, fp) != NULL) { int len = strlen(buf); if(buf[len-1] == '\n') buf[len-1] = '\0'; printf("%s\r\n", buf); } if((rc = pclose(fp)) < 0) { perror("pclose error!"); return -1; } return 0; }######回复 @txgcwm : 但是在主函数中,调用相关函数经常出现“undefined reference to”的错误,这些错误我有些不能理解。我在网上也看了一些相关的资料,但是是没能解决,希望你给点建议。######回复 @Hyacinthus_M : 给你一个大概的思路: 1、从数据上看,每个wifi信息都是以cell开头的,以此为标记; 2、使用isspace函数将前面的所有空格清除; 3、通过strcmp对比你要获取的数据项,然后将其后的数据保存。 你自己尝试解析,后续有问题,下班了再说。######回复 @txgcwm : 就是。我觉得他个人有点偏执。同样是用上层。他是把这个任务交给我的。我的公司小,只有十个人,其中几个还是实习的。我先用解析的方法做出来,如果有什么不懂的,还要请教你啊。 对了,设置关键字字符串数组,每一行一行的解析,是不是用strstr()简单来对每一行的内容与关键字进行配对来过滤内容就可以了?######回复 @Hyacinthus_M : 这个我也不太清楚哪里有这些资料,你自己去找找吧。无论你是去修改wireless tools还是按照解析输出数据的方法,也只是上层应用。如果要从内核的层次去了解这些东西,预计你一周的时间根本不够。 不太清楚你的主管需要你用什么样的方法实现?他固执的要用自己的方法(他自身是否对这些可能用到的方法作过分析?),他自己为什么不去实现。######回复 @txgcwm : 我把自己的想法和他说了,他还是让我熟悉底层的API(意思还是让我去修改wireless-tools)。先把用这个实现方法做出来吧。用wireless-tools修改程序的方法,和解析输出的方法没有本质区别吧。 对了,基于无线网络开发的API在哪能找到资料?难道要去看kernel?

kun坤 2020-06-06 13:38:52 0 浏览量 回答数 0

问题

第6篇 指针数组字符串(下)补充:报错

kun坤 2020-06-08 11:02:03 3 浏览量 回答数 1

问题

Nginx性能为什么如此吊

小柒2012 2019-12-01 21:20:47 15038 浏览量 回答数 3

问题

关于dll中全局变量的问题 400 请求报错 

kun坤 2020-05-30 14:30:23 0 浏览量 回答数 1

问题

【精品问答】Python二级考试题库

珍宝珠 2019-12-01 22:03:38 1146 浏览量 回答数 2
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 企业信息查询 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站