面試積累【記下哪些被虐的細節】
public void print() {
if ( ) {
System.out.print("a");
} else {
System.out.print("b");
}
}
腦洞大開的做法:
public void print() {
// if ( ) {
System.out.print("a");
// } else {
System.out.print("b");
// }
}
套路解法:
填入內容 true){System.out.print(“a”);}if(false。
public void print() {
if (true) {
System.out.print("a");
}
if (false) {
System.out.print("a");
} else {
System.out.print("b");
}
}
類似地也可以填入 true){System.out.print(“ab”);return;}if(false 等。
當初大學時單純的少年可是很難想出這樣的套路的,時間改變了我們啊
————————————————->
#define AAA 100
#define BBB AAA+100
#define CCC BBB*2
printf("%d",CCC);
/*結果輸出是: 300 */
/*今天面試的那個工程師錯了*/
有關記憶體洩露和記憶體溢位的試題:
如何防止記憶體洩露?如何檢查記憶體洩露?
http://www.cnblogs.com/Sharley/p/5285045.html
記憶體洩漏:是指你向系統申請分配記憶體進行使用(new),可是使用完了以後卻不歸還(delete),結果你申請到的那塊記憶體你自己也不能再訪問(也許你把它的地址給弄丟了),而系統也不能再次將它分配給需要的程式。一個盤子用盡各種方法只能裝4個果子,你裝了5個,結果掉倒地上不能吃了。這就是溢位!比方說棧,棧滿時再做進棧必定產生空間溢位,叫上溢,棧空時再做退棧也產生空間溢位,稱為下溢。就是分配的記憶體不足以放下資料項序列,稱為記憶體溢位
以發生的方式來分類,記憶體洩漏可以分為4類:
1. 常發性記憶體洩漏。發生記憶體洩漏的程式碼會被多次執行到,每次被執行的時候都會導致一塊記憶體洩漏。
2. 偶發性記憶體洩漏。發生記憶體洩漏的程式碼只有在某些特定環境或操作過程下才會發生。常發性和偶發性是相對的。對於特定的環境,偶發性的也許就變成了常發性的。所以測試環境和測試方法對檢測記憶體洩漏至關重要。
3. 一次性記憶體洩漏。發生記憶體洩漏的程式碼只會被執行一次,或者由於演算法上的缺陷,導致總會有一塊僅且一塊記憶體發生洩漏。比如,在類的建構函式中分配記憶體,在解構函式中卻沒有釋放該記憶體,所以記憶體洩漏只會發生一次。
4. 隱式記憶體洩漏。程式在執行過程中不停的分配記憶體,但是直到結束的時候才釋放記憶體。嚴格的說這裡並沒有發生記憶體洩漏,因為最終程式釋放了所有申請的記憶體。但是對於一個伺服器程式,需要執行幾天,幾周甚至幾個月,不及時釋放記憶體也可能導致最終耗盡系統的所有記憶體。所以,我們稱這類記憶體洩漏為隱式記憶體洩漏。
記憶體溢位和記憶體洩露是兩個問題。
記憶體洩露在除錯的時候可能發現不了但是應用上線後可能就會暴露【小型潛入式系統這類問題比較少見】。
—————————————->
#include <stdio.h>
#include <stdlib.h>
/**/
#if 0
void strcopy(char *dst,char* src)
{
while((*dst++ = *src++)!='\0');
}
#elif 0
//將源字串加const,表明其為輸入引數,加2分
strcopy( char *strDest, const char *strSrc )
{
while((*strDest++=*strSrc++)!='\0');
}
#elif 0
void strcopy(char *dst,const char *src)
{
if((dst)&&(src)){
/*assert( (strDest != NULL) && (strSrc != NULL));*/
while((*dst++=*src++)!='\0');
}else{
printf("error in argv\n");
}
}
#elif 1
/*為了實現鏈式操作,將目的地址返回,加3分!*/
char * strcopy(char *dst,const char *src)
{
char *ret=dst;
if((dst)&&(src)){
/*assert( (strDest != NULL) && (strSrc != NULL));*/
while((*dst++=*src++)!='\0');
return ret;
}else{
printf("error in argv\n");
return NULL;
}
}
#endif
/********************************/
/****形參的頂級陷阱***/
void getmem(char *p)
{
p = malloc(100);
}
char *p = NULL;
getmem(p);
if(NULL==p)
printf("fuck empty\n");/*p沒有被改變*/
/*******************************/
/**********************/
#define AAA 100
#define BBB AAA+100
#define CCC BBB*2
printf("%d\n",CCC);//300
/**********************/
int main(void)
{
char dst[6]="";
char src[6]="hello";
// char *dst=NULL;
strcopy(dst,src);
if(dst)
printf("%s\n",dst);
return 0;
}
編寫一個函式【可以編譯】輸入年月日時分秒,能計算出下一面的年月日時分秒:如輸入2000年2月28日-23點59秒59分,能輸出2000年2月29日-00點00分00秒
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
void ResetTheTime(int *year,int *month,int *date,int *hour,int *minute,int*second)
{
int dayOfMonth[12]={31,28,31,30,31,30,31,31,30,31,30,31};
if( *year < 0 || *month < 1 || *month > 12 ||
*date < 1 || *date > 31 || *hour < 0 || *hour > 23 ||
*minute < 0 ||*minute > 59|| *second <0 || *second >60 )
return;
if( *year%400 == 0 || *year%100 != 0 && *year%4 == 0 )
dayOfMonth[1] = 29;
++(*second);
if(*second >= 60)
{
*second = 0;
*minute += 1;
if(*minute >= 60)
{
*minute = 0;
*hour += 1;
if(*hour >= 24)
{
*hour = 0;
*date += 1;
if(*date > dayOfMonth[*month-1])
{
*date = 1;
*month += 1;
if(*month > 12)
{
*month=1;*year += 1;
}
}
}
}
}
return;
}
int main(void)
{
int year=2001,
month=2,
date = 28,
hour=23,
minute=58,
second=59;
while(1){
ResetTheTime(&year,&month,&date,&hour,&minute,&second);
printf("%d-%d-%d > %d:%d:%d\n",year,month,date,hour,minute,second);
usleep(1000);
//second++;
}
}
關於記憶體和棧的區別:
這裡的棧和堆的東西其本質應該是一種資料結構【佇列,棧,連結串列】
堆和棧的區別:
一、堆疊空間分配區別:
1、棧(作業系統):由作業系統自動分配釋放 ,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧;
2、堆(作業系統): 一般由程式設計師分配釋放, 若程式設計師不釋放,程式結束時可能由OS回收,分配方式倒是類似於連結串列。
二、堆疊快取方式區別:
1、棧使用的是一級快取, 他們通常都是被呼叫時處於儲存空間中,呼叫完畢立即釋放;
2、堆是存放在二級快取中,生命週期由虛擬機器的垃圾回收演算法來決定(並不是一旦成為孤兒物件就能被回收)。所以呼叫這些物件的速度要相對來得低一些。
三、堆疊資料結構區別:
堆(資料結構):堆可以被看成是一棵樹,如:堆排序;
棧(資料結構):一種先進後出的資料結構。