庄周梦蝶

生活、程序、未来
   :: 首页 ::  ::  :: 聚合  :: 管理

一、什么时候数组和指针是相同的
1、表达式中的数组名(与声明不同)被编译器当作一个指向该数组第一个元素的指针
因此如a[i]这样的访问都被编译器改写或解释为*(a+i)的形式,同样取下标操作符的操作数是可交换的,所以a[3]可以写成3[a],不过通常你不会这样做。

2、下标总是与指针的偏移量相同,下标*sizeof(元素类型)就是偏移数组起始地址的实际字节数。

3、“作为函数参数的数组名”等同于指针,任何传递给函数的数组参数都会被转换成指针,这是基于效率考虑,避免了数组的拷贝。在函数内部,数组参数都将被转换成一个指针,要牢记这一点,因此如:
void test(char a[10])
{
   printf(
"%d\n",sizeof(a));
}

显然应该打印指针大小4,而非数组大小。另外,注意数组参数的地址跟数组参数第一个元素的地址并不相等,在表达式中两者一致,但是在函数调用中,由于数组参数指针也是临时变量,因此两者的地址是不一样的。
可以通过下列程序观察:

#include <stdio.h>
#include 
<stdlib.h>
void test1(char a[])
{
    printf(
"&a=%x,&(a[0])=%x,&(a[1])=%x\n",&a,&(a[0]),&(a[1]));
}
void test2(char *b)
{
    printf(
"&b=%x,&(b[0])=%x,&(b[1])=%x\n",&b,&(b[0]),&(b[1])); 
}
int main(int argc, char *argv[])
{
  
char ga[]="hello";
  printf(
"&ga=%x,&(ga[0])=%x,&(ga[1])=%x\n",&ga,&(ga[0]),&(ga[1])); 
  test1(ga);
  test2(ga);
  system(
"pause");
  
return 0;
}


二、指针跟数组什么时候不同
1、如果定义了一个数组,在其他文件对它进行声明也必须声明为数组,定义和声明必须匹配,指针也是如此。
2、指针始终是指针,它绝不可以写成数组。可以用下标形式访问指针的时候,一般都是指针作为函数参数时,并且你知道传递给函数的实际是一个数组。
3、数组名是不可改变的左值,因此如
int array[100],array2[100];
array
=array2;
array++;
array--;
 
都将出错,但是在函数内部:

int array2[100];
void fun(int array[])
{
  array
=array2;
}

却可以,因为在函数内部array虽然被声明为数组实际上却是指针。






posted @ 2009-02-17 00:05 dennis 阅读(1971) | 评论 (4)编辑 收藏

   最近的心情可以用一首歌来形容,阿岳的《无路用的人》,唱到心坎里了。无路用是闽南语,是指一个人没啥出息,没做出什么事情。在厦门一个多月了,有点不坚定,有点彷徨,有点郁闷,无以形容。

每天我醒来在床上就在发呆
我的脑袋跟天花板一样空白
昨天在干嘛 明天要干嘛
我的灵魂 似乎不在我的身上
唉呀 未接电话那么多
我想 狗屁事也非常多
好希望 这是一场梦
可以让我 轻轻松松忘掉很多
哇勒干 怎么可能会是一场梦呢
我很自由 可是没有工作
是一种痛苦的自由
我在惊什么 我在怕什么
也许 自由 是我逃避的借口
谁能够告诉我 我哪里出了错
反省 是多么重要的事情
可是我到最近才慢慢了解
笨蛋 这两个字我常常骂别人
现在 我只会骂我自己
我了解自己吗 不知道
都已经几岁了 还不知道
这几年 用尽所有力气
试图证明我跟别人不一样 懒觉啦
我的白痴自信和白痴骄傲 害了我
我很欠骂 我是傻瓜 我好辛苦 失去方向
我在怀疑 我在忍耐 我在等待 我在干嘛
我很欠骂 我是傻瓜 我好辛苦 失去方向
我在怀疑 我在忍耐 我在等待 我在干嘛
我很欠骂 我是傻瓜 我好辛苦 失去方向
我在怀疑 我在忍耐 我在等待 我在干嘛
我很欠骂 我是傻瓜 我好辛苦 来 跟我一起唱
一起唱 一起唱 一起唱
一起唱 一起唱 一起唱
度日如年哪 支离破碎的生活
我就象是没灵魂 在街上晃呀晃
象一滩死水 一种绝望的感觉
没有多余的眼泪来可怜自己
没有人陪我 寂寞的街上
霓虹灯闪耀 它似乎在笑我
哈哈哈 无路用的人
一起唱 一起唱 一起唱
度日如年哪 支离破碎的生活
我就象是没灵魂 在街上晃呀晃
象一滩死水 一种绝望的感觉
没有多余的眼泪来可怜自己
没有人陪我 寂寞的街上
霓虹灯闪耀 它似乎在笑我
哈哈哈 无路用的人
一起唱 一起唱 一起唱
度日如年哪 支离破碎的生活
我就象是没灵魂 在街上晃呀晃
象一滩死水 一种绝望的感觉
没有多余的眼泪来可怜自己
没有人陪我 寂寞的街上
霓虹灯闪耀 它似乎在笑我
哈哈哈 无路用的人
一起唱 一起唱 一起唱
啦...啦...啦...啦...
无路用的人



posted @ 2009-02-16 22:36 dennis 阅读(506) | 评论 (2)编辑 收藏

    俺的山寨nio框架yanf4j发布0.50-alpha版本,下载地址在这里,更新了wiki。本测试版本主要修改如下:
1、Controller接口引入了两个新方法

a)接受InetSocketAddress类型参数的系列open方法,用以在多宿主机上绑定到不同网络接口
     
    
public void open(InetSocketAddress inetSocketAddress, boolean reuseAddr,
            Handler handler, CodecFactory codecFactory) 
throws IOException;
    
public void open(InetSocketAddress inetSocketAddress, boolean reuseAddr,
            Handler handler) 
throws IOException;
    
public void open(InetSocketAddress inetSocketAddress, Handler handler)
            
throws IOException;
    
public void open(InetSocketAddress inetSocketAddress, Handler handler,
            CodecFactory codecFactory) 
throws IOException;

b)wakeup()方法,用以唤醒阻塞在select调用上的reactor,此方法的重载版本可以传入session和 EventType指定触发


    
public void wakeup();
    
public void wakeup(Session session, EventType eventType);

通常来说,你并不需要用到此方法。

2、TCPController添加了backlog的getter和setter方法,用以设置backlog队列大小

   
public int getBacklog();
  
public void setBacklog(int backlog);

3、reuseAddress默认修改为false,防止服务器悄无声息地启动出错,除非你明确指定。

4、修复数个bug,如session启动未注册到controller、关闭session在异常情况下Controller没有移除session可能造成内存泄露等问题

5、一些优化手段,依照ACE建议调整事件派发顺序等

6、一些重构,因为早期AbstractController并不庞大,因而将Reactor作为它的内部类实现,现在随着代码的添加,AbstractController变的复杂难懂,因而将Reactor从AbstractController抽离成独立的类,引入新的接口如SessionEventManager、ControllerLifeCycle、ControllerWrapper以及SelectionKeyHandler等。

7、可以在jdk5.0下使用yanf4j了,原来仅支持1.6以上,不过你需要自己编译,二进制包仍然仅提供jdk6.0编译版本。

posted @ 2009-02-04 19:28 dennis 阅读(1936) | 评论 (0)编辑 收藏

    ACE_Reactor在windows上默认不是使用ACE_Select_Reactor,而是ACE_WFMO_Reactor(封装了WaitForMultipleObjects和WSAEventSelect)。如果想选择ACE_Select_Reactor,如:

ACE_Select_Reactor select_reactor;
ACE_Reactor reactor (
&select_reactor);

    那么VC需要启用/GR编译选项,具体做法就是在项目属性c/c++的语言一栏中启用RTTI信息即可。在选择了ACE_Select_Reactor之后,启动进程后在ProcessExplorer果然可以看到进程的TCP属性中建立了两个互连的TCP连接,用以notify的实现。





posted @ 2009-02-03 15:40 dennis 阅读(879) | 评论 (0)编辑 收藏

相对完整的修改版本

  1 /************************************************************************ 
  2 * @file: echo.cpp                                                    
  3 * @author: dennis
  4 * @revise: dennis <killme2008@gmail.com> http://www.blogjava.net/killme2008
  5 *          相对完整的echo server,可以接受多个客户端连接,并且可以通过键入quit正常关闭
  6 
  7 ************************************************************************/
  8 
  9 #ifdef _DEBUG
 10 #pragma comment (lib,"aced.lib")
 11 #else
 12 #pragma comment (lib,"ace.lib")
 13 #endif
 14 
 15 #include "ace/Reactor.h"
 16 #include "ace/SOCK_Acceptor.h"
 17 #include "ace/os.h"
 18 #include "ace/Log_Msg.h"
 19 #include "ace/inet_addr.h"
 20 #include "ace/Thread_Manager.h"
 21 #include<iostream>
 22 #include<string>
 23 
 24 #define PORT_NO 8080
 25 typedef ACE_SOCK_Acceptor Acceptor;
 26 //forward declaration
 27 class Echo_Handler;
 28 
 29 class Echo_Handler:public ACE_Event_Handler
 30 {
 31 public:
 32     //construcor
 33     Echo_Handler()
 34     {
 35     }
 36     virtual ~Echo_Handler()
 37     {
 38     }
 39     //Called back to handle any input received
 40     int handle_input(ACE_HANDLE)
 41     {
 42         //receive the data
 43         ssize_t recvBytes = peer().recv(data,12);
 44         if(recvBytes <= 0)
 45         {
 46             ACE_DEBUG((LM_DEBUG,"%s\n","客户端断开连接"));
 47             return -1;
 48         }
 49         data[recvBytes] = 0;
 50 
 51         ACE_DEBUG((LM_DEBUG,"%s\n",data));
 52 
 53 
 54         if(ACE_OS::strcmp(data,"q"== 0)
 55         {
 56             ACE_DEBUG((LM_DEBUG,"%s\n","客户端退出"));
 57             peer().close();
 58             return -1;
 59         }
 60         peer().send_n(data,recvBytes);
 61         // do something with the input received.
 62         // 
 63         // keep yourself registerd with the reator
 64         return 0;
 65     }
 66 
 67     int handle_close(ACE_HANDLE h,ACE_Reactor_Mask m)
 68     {
 69         delete this;
 70         return  0;
 71     }
 72 
 73     //Used by the reactor to determine the underlying handle
 74     ACE_HANDLE get_handle()  const 
 75     {
 76         return this->peer_.get_handle();
 77     }
 78 
 79     //Returns a reference to the underlying stream.
 80     ACE_SOCK_Stream& peer()
 81     {
 82         return this->peer_;
 83     }
 84 
 85 private:
 86     ACE_SOCK_Stream peer_;
 87     char data [12];
 88 };
 89 
 90 class Echo_Accept_Handler:public ACE_Event_Handler
 91 {
 92 public:
 93     //Constructor
 94     Echo_Accept_Handler(ACE_Addr &addr)
 95     {
 96         this->open(addr);
 97     }
 98     virtual ~Echo_Accept_Handler(){}
 99     //Open the peer_acceptor so it starts to "listen"
100     //for incoming clients
101     int open(ACE_Addr &addr)
102     {
103         if(peer_acceptor.open(addr)==-1)
104             ACE_ERROR_RETURN((LM_ERROR,"启动服务器错误\n"),1);
105         return 0;
106     }
107 
108     //Overload the handle input method
109     int handle_input(ACE_HANDLE handle)
110     {
111         //Client has requested connection to server.
112         //Create a handler to handle the connection
113         Echo_Handler *eh;
114         ACE_NEW_RETURN(eh,Echo_Handler,-1);
115         ACE_INET_Addr cliaddr;
116         //Accept the connection "into" the Event Handler
117         if(this->peer_acceptor.accept(eh->peer(),//stream
118             &cliaddr,//remote address
119             0,//timeout
120             1== -1)//restart if interrupted
121             ACE_DEBUG((LM_ERROR,"Error in connection \n"));
122 
123         ACE_DEBUG((LM_DEBUG,"连接已经建立,来自%s\n",cliaddr.get_host_addr()));
124 
125         //Register the input event handler for reading 
126         ACE_Reactor::instance()->register_handler(eh,ACE_Event_Handler::READ_MASK);
127         const char* msg = "按q键使服务安全退出\r\n";
128         eh->peer().send_n(msg,strlen(msg)+1);
129         return 0;
130     }
131 
132     //Used by the reactor to determine the underlying handle
133     ACE_HANDLE get_handle(voidconst
134     {
135         return this->peer_acceptor.get_handle();
136     }
137     int handle_close(ACE_HANDLE h,ACE_Reactor_Mask m){
138         peer_acceptor.close();
139         delete this;
140         return 0;
141     }
142 
143 private:
144     Acceptor peer_acceptor;
145 };
146 class Quit_Handler:public ACE_Event_Handler
147 {
148 public:
149     Quit_Handler(ACE_Reactor* r):ACE_Event_Handler(r){}
150     virtual int handle_exception(ACE_HANDLE)
151     {
152         ACE_DEBUG((LM_DEBUG,"停止服务器中\n"));
153         reactor()->end_reactor_event_loop();
154         return -1;
155     }
156     int handle_close(ACE_HANDLE h,ACE_Reactor_Mask m)
157     {
158         delete this;
159         return 0;
160     }
161     virtual ~Quit_Handler(){}
162 };
163 static ACE_THR_FUNC_RETURN run_events (void *arg);
164 static ACE_THR_FUNC_RETURN controller (void *arg);
165 int ACE_TMAIN(int argc,char *argv[])
166 {
167 
168     ACE_Reactor* reactor=ACE_Reactor::instance();
169     if(ACE_Thread_Manager::instance()->spawn(run_events,reactor,THR_DETACHED | THR_SCOPE_SYSTEM)==-1)
170         return 1;
171     if(ACE_Thread_Manager::instance()->spawn(controller,reactor,THR_DETACHED | THR_SCOPE_SYSTEM)==-1)
172         return 1;
173     return ACE_Thread_Manager::instance()->wait();
174 }
175 
176 static ACE_THR_FUNC_RETURN run_events (void *arg)
177 {
178     ACE_Reactor* reactor=ACE_static_cast(ACE_Reactor*,arg);
179     ACE_INET_Addr addr(PORT_NO);
180 
181     Echo_Accept_Handler *eh=0;
182     ACE_NEW_RETURN(eh,Echo_Accept_Handler(addr),1);
183 
184     ACE_Reactor::instance()->owner(ACE_OS::thr_self());
185     reactor->register_handler(eh,ACE_Event_Handler::ACCEPT_MASK);
186     ACE_Reactor::instance()->run_reactor_event_loop();
187     return 0;
188 }
189 static ACE_THR_FUNC_RETURN controller (void *arg)
190 {
191     ACE_Reactor* reactor=ACE_static_cast(ACE_Reactor*,arg);
192     Quit_Handler *quit_handler=0;
193     ACE_NEW_RETURN(quit_handler,Quit_Handler(reactor),1);
194     for(;;)
195     {
196         std::string line;
197         std::getline(std::cin,line,'\n');
198         if(line=="quit"){
199             ACE_DEBUG((LM_DEBUG,"请求停止服务器\n"));
200             reactor->notify(quit_handler);
201             break;
202         }
203     }
204     return 0;  
205 }
206 


posted @ 2009-02-03 11:59 dennis 阅读(1685) | 评论 (1)编辑 收藏

    过去推荐过两篇blog《Java NIO类库Selector机制解析》(),感叹java为了跨平台似乎“很傻很天真”。最近学习使用ACE,才知道这个解决办法倒不是java开创的,ACE也是这样搞的。java nio中Selector的wakeup方法,类似于ACE_Select_Reactor的notify机制,可以从非select调用的线程去唤醒阻塞在select调用上的select线程,当然ACE_Select_Reactor的notify强大多了,可以实现event handler的无限扩容。ACE_Select_Reactor的notify的实现是通过ACE_Pipe,在ACE_Pipe中可以清晰地看到针对win32平台是采用了TCP连接:

#if defined (ACE_LACKS_SOCKETPAIR) || defined (__Lynx__)
  ACE_INET_Addr my_addr;
  ACE_SOCK_Acceptor acceptor;
  ACE_SOCK_Connector connector;
  ACE_SOCK_Stream reader;
  ACE_SOCK_Stream writer;
  
int result = 0;
if defined (ACE_WIN32)
  ACE_INET_Addr local_any  (static_cast
<u_short> (0), ACE_LOCALHOST);
else
  ACE_Addr local_any 
= ACE_Addr::sap_any;
# endif 
/* ACE_WIN32 */

  
// Bind listener to any port and then find out what the port was.
  if (acceptor.open (local_any) == -1
      
|| acceptor.get_local_addr (my_addr) == -1)
    result 
= -1;
  
else
    {
      ACE_INET_Addr sv_addr (my_addr.get_port_number (),
                             ACE_LOCALHOST);

      
// Establish a connection within the same process.
      if (connector.connect (writer, sv_addr) == -1)
        result 
= -1;
      
else if (acceptor.accept (reader) == -1)
        {
          writer.close ();
          result 
= -1;
        }
    }

  
// Close down the acceptor endpoint since we don't need it anymore.
  acceptor.close ();

    在类unix平台是采用STREAMS管道,在一些遗留的unix平台上是socketpair()。为什么在win32上采用TCP连接的方式呢?原因不是什么性能、资源问题,也不是因为windows管道消耗的资源比tcp多,而是由于winsock的select函数(java nio的select在win32下是使用select实现的)是无法监测管道事件的,也就是说无法将windows管道加入到fd_set中,为了做到可移植,才在win32上采用了TCP连接的方式来实现。这一点在blog上篇的新回复中已经有人提到。

posted @ 2009-02-01 11:15 dennis 阅读(3357) | 评论 (0)编辑 收藏

    这几天没事做的时候都会上projecteuler.net上面去做题,其中14题是这样的:
he following iterative sequence is defined for the set of positive integers:

n → n/2 (n is even)
n → 3n + 1 (n is odd)

Using the rule above and starting with 13, we generate the following sequence:

13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1

It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.

Which starting number, under one million, produces the longest chain?


    题目并不难理解,这个据说是著名的角谷猜想,现在要找到100万以下的数字中展开这个链最长的数字是多少。如果我一开始就直接按照题意来解答,这个题目花不了几分钟,直接暴力法。然而我却想的太多了,我猜想在计算这个链条长度的过程中会不会有很多数字会重复计算,如果加上缓存以前计算的结果是否能节约比较多的时间?那么第一次解答如下:

#include<iostream>
#include
<map>
#include
<windows.h>
using namespace std;
unsigned 
long produce_term(unsigned long n)
{
    
if(n&1)
        
return 3*n+1;
    
else
        
return n>>1;
}
int main()
{
    map
<unsigned long,int> counters;
    
int max_i=0;
    
int max_count=0;
    DWORD tick1,tickPassed;
    tick1 
= GetTickCount(); 
    
for(int i=1;i<1000000;i++)
    {
        
int sum=2;
        unsigned 
long term=i;
        
while((term=produce_term(term))!=1)
        {
            
if(counters[term]){
                sum
+=counters[term];
                
break;
            }
else
                sum
+=1;
        }

        
if(sum>max_count)
        {
            max_i
=i;
            max_count
=sum;
            counters[i]
=sum;
        }

    }
    tickPassed 
= GetTickCount()-tick1; 
    cout
<<tickPassed<<endl;
    cout
<<max_i<<endl<<max_count<<endl;
    
return 0;
}
  
    遗憾的是,这个版本跑了快13分钟,太让人难以接受了。那么是否能优化下?怎么优化?我的机器是双核的,跑这个单进程单线程的程序只利用了一半的CPU,那么能不能搞成两个线程来计算?缓存需要在两个线程之间做同步,显然读的多,写的少,应该采用读写锁。OK,第二个版本利用ACE的线程封装实现如下:
#include<iostream>
#include
<map>
#include 
"ace/Thread_mutex.h"
#include 
"ace/Synch.h"
#include 
"ace/Thread_Manager.h"
using namespace std;
class ThreadSafeMap
{
public:
    ThreadSafeMap()
    {
    }
    
int get(unsigned long n)
    {
        ACE_READ_GUARD_RETURN(ACE_RW_Thread_Mutex,guard,mutex_,
0);
        
return counters_[n];
    }
    
int put(unsigned long key,int value)
    {
        ACE_WRITE_GUARD_RETURN(ACE_RW_Thread_Mutex,guard,mutex_,
-1);
        counters_[key]
=value;
        
return 0;
    }

private:
    map
<unsigned long,int> counters_;
    ACE_RW_Thread_Mutex mutex_;
};
unsigned 
long produce_term(unsigned long n)
{
    
if(n&1)
        
return 3*n+1;
    
else
        
return n>>1;
}
static ThreadSafeMap counters;
ACE_THR_FUNC_RETURN run_svc (
void *arg)
{
    
int max_i=0;
    
int max_count=0;
    
for(int i=500001;i<1000000;i++)
    {
        
int sum=2;
        unsigned 
long term=i;
        
while((term=produce_term(term))!=1)
        {
            
if(counters.get(term)){
                sum
+=counters.get(term);
                
break;
            }
else
                sum
+=1;
        }

        
if(sum>max_count)
        {
            max_i
=i;
            max_count
=sum;
            counters.put(i,sum);
        }

    }
    cout
<<max_i<<endl<<max_count<<endl;
    
return 0;
}
int main(int ac,char* argv[])
{
    
if (ACE_Thread_Manager::instance ()->spawn (
        
// Pointer to function entry point.
        run_svc,
        
// <run_svc> parameter.
        NULL,
        THR_DETACHED 
| THR_SCOPE_SYSTEM) == -1)
        
return -1;
    
int max_i=0;
    
int max_count=0;

    
for(int i=1;i<500000;i++)
    {
        
int sum=2;
        unsigned 
long term=i;
        
while((term=produce_term(term))!=1)
        {
            
if(counters.get(term)){
                sum
+=counters.get(term);
                
break;
            }
else
                sum
+=1;
        }

        
if(sum>max_count)
        {
            max_i
=i;
            max_count
=sum;
            counters.put(i,sum);
        }

    }
    cout
<<max_i<<endl<<max_count<<endl;
    
return ACE_Thread_Manager::instance ()->wait ();
}
   
    将数据分成了两半,利用两个线程来计算,果然快了一点,快了多少呢?从13分钟减少到9分钟,CPU利用率也到了100%,内存占用也降低了一半,似乎成绩不错呀。正在沾沾自喜之际,突然想起,能不能简单地暴力破解,咱不搞缓存,不搞多线程,看看效果怎么样。那么第三个版本简单实现如下:
#include<iostream>
using namespace std;
unsigned 
long produce_term(unsigned long n)
{
    
if(n&1)
        
return 3*n+1;
    
else
        
return n>>1;
}
int main()
{
  
int max_i;
  
int max_count=0;
  
for(int i=1;i<1000000;i++)
  {
     
int count=2;
     unsigned 
long term=i;
     
while((term=produce_term(term))>1)
         count
+=1;
     
if(count>max_count){
           max_i
=i;
           max_count
=count;
     }
  }
  cout
<<max_i<<endl<<max_count<<endl;
  system(
"pause");
  
return 0;
}

    程序执行的结果让我惊掉了下巴,竟然只执行了1秒多,换成java也是一样。什么缓存、多线程,全抛到了九霄云外。

     总结教训,想当然的性能估计是愚不可及的,想当然的优化是愚不可及的,简单直接才是美!

posted @ 2009-01-23 00:08 dennis 阅读(605) | 评论 (3)编辑 收藏

项目名称:yanf4j (yet another nio framework for java)
项目网址:http://code.google.com/p/yanf4j/
下载网址:http://code.google.com/p/yanf4j/downloads/list

0.41 beta版的主要修改:

1、引入流量控制,通过Controller的setReceivePacketRate方法设置接收消息频率(单位 个/秒),当超过设定值时,yanf4j将放缓接收数据直到实时统计的接收频率降低。此功能默认未开启。
2、改善了数据统计,数据统计不再是从服务器启动时间点到当前的时间段内的平均统计,而是以一定时间间隔做统计,每隔这个时间段就重新开始数据统计。因此可以反映出不同时间段的流量。默认这个统计区间间隔是5分钟,可设置。
3、重构部分代码,引入Controller接口,修改部分命名不当的API等。

posted @ 2009-01-20 14:01 dennis 阅读(1813) | 评论 (0)编辑 收藏

    在cpp中为了可移植性,string的长度是string::size_type,突然就想知道java允许的最大字符串长度为多少。看String的源码:
public final class String
  
110       implements java.io.Serializable, Comparable<String>, CharSequence
  
111   {
  
112       /** The value is used for character storage. */
  
113       private final char value[];
  
114   
  
115       /** The offset is the first index of the storage that is used. */
  
116       private final int offset;
  
117   
  
118       /** The count is the number of characters in the String. */
  
119       private final int count;
   String内部是以char数组的形式存储,数组的长度是int类型,那么String允许的最大长度就是Integer.MAX_VALUE了。又由于java中的字符是以16位存储的,因此大概需要4GB的内存才能存储最大长度的字符串。不过这仅仅是对字符串变量而言,如果是字符串字面量(string literals),如“abc"、"1a2b"之类写在代码中的字符串literals,那么允许的最大长度取决于字符串在常量池中的存储大小,也就是字符串在class格式文件中的存储格式:
CONSTANT_Utf8_info {
        u1 tag;
        u2 length;
        u1 bytes[length];
}

    u2是无符号的16位整数,因此理论上允许的string literal的最大长度是2^16-1=65535。然而实际测试表明,允许的最大长度仅为65534,超过就编译错误了,有兴趣可以写段代码试试,估计是length还不能为0。

posted @ 2009-01-15 01:37 dennis 阅读(62495) | 评论 (7)编辑 收藏

    昨天晚上6点多,从惠安老家到泉州去做到广州的长途汽车。中途汽车轮胎破了,坐这么久汽车还是第一次遇到,耽搁了一段时间,最后没赶上7点多的车,只好等待8点半的班车了。晚上的候车室冷冷清清,找了个没人的座位坐下,一转头,才发现旁边放着一个蓝色的大旅行包,包的主人没看见,下意识地赶紧找个离的远点的座位坐下。时常听他人讲,看见钱包之类的东西不要拣,因为很可能是骗局,何况这么大一旅行包,万一丢了什么东西赖我身上可怎么办。坐下来喝了点水,吃点面包的时候才想起,我什么时候也变的这么小心翼翼了?
    候车室大灯都关了,只有停车场的汽车灯光照进来隐约可见,天气还是很冷,庆幸前天买了件外套,不然得冻死掉。老家就是风大,毕竟离海边近,凉飕飕的从门口吹进来。蓝色旅行包的主人回来了,看情况是去上厕所,我还暗想他怎么能这么不小心呢,不知道现在拎包党很猖獗吗?那人看起来看挺年轻,不过可能比我大,深色夹克,脚上的尖头皮鞋也搽的挺亮,短发,让人看起来精神不错。打量两眼,我还是玩我的手机游戏打发时间,离上车时间还有半个多小时。
    我正玩的不亦乐乎,突然听到似乎有人在对我说话。转头一看,是那位大哥冲我说着什么。我们隔了4,5个座位,我没听清,请他再说了一遍,才知道是问我说这附近有没有工厂。泉州过去一点就是晋江石狮,那边工厂是很多的,泉州跟晋江也就隔着一条江,过了大桥就是晋江。我就如此这般跟他说了下。然后他又问这候车室会不会关门,我说我也不清楚了这个情况了,问他怎么问这个。他说他问保安能不能睡在马路上,保安说随便,怕治安不好,所以进来这里,又担心这里晚点会关门。我有点明白怎么回事了,敢情这大哥没地方睡觉才来这里的啊。我就说泉州治安还是不错的,这里关门不关门我是不知道的,我不是泉州市内的。然后这大哥主动跟我介绍说是重庆来的,刚到泉州,手头上只剩4块,这边旅馆都至少要20,30块的,住不起了。我有点无言以对,这是在要钱吗?看样子也不是那意思,我就跟他聊了聊。原来他是家里老六,兄弟姐妹都成婚了,一个人出来跑,听他一个回重庆的老乡介绍说到厦门出海很赚钱,就跑过来了,到厦门劳务市场一问,要到打渔公司需要办一张450块钱的渔民证才让应聘,他没钱,就听说泉州这边工厂多,剩下一点钱就坐车到这里来了,想先找在工厂找份工作做,然后再打算。我是听我同学说过,出海是挺赚钱的,不过很辛苦,一次出海打渔都要几个月在海上漂,回来能赚上万甚至几万块钱,具体的情况就不清楚了,工厂泉州是很多,不过最近常听到的就是工厂倒闭很多,招不招工也不清楚了,不过找到工作的机会还是比较大的,去年还听说我们这边闹民工荒。我将这情况跟他说一下,建议他去晋江看看那边的工厂招人不,不好意思帮不上什么忙。突然想起他说只剩4块钱,晚饭应该还没吃,我带了一些糖果和面包准备到广州去的,想想就分了些粽子、面包给他,犹豫了下也给了20块钱。他连说谢谢,说没遇到过我这样年轻的好心人。我很惭愧,我能做的也只有这样了,我的廉价的同情也仅仅能帮助他度过一个晚上罢了。我说我也是打工的,我明白一个人出来跑的感觉。
    我问他重庆不是挺好的,为什么跑这么远出来。他说趁年轻想出来跑跑,再说家里兄弟姐妹都成婚了,自己也要努力下。我说我也是出去打工的,到广州混饭吃,这次回来结婚,他很高兴地恭喜我。我看看时间差不多了,就收拾下东西准备上车了,临走前祝福他找到好工作。我在想如果他没有找到工作,到了绝境他会怎么办,我不敢也不忍去想。不过我还是相信天无绝人之路,以此日志,仅做记录。
   
   

posted @ 2008-12-09 17:03 dennis 阅读(664) | 评论 (8)编辑 收藏

仅列出标题
共56页: First 上一页 19 20 21 22 23 24 25 26 27 下一页 Last