编程技术是改变世界的力量。
本站
当前位置:网站首页 > 后端语言 > 正文

C语言常用技巧和易错题汇总(一)(c语言常见例题)

gowuye 2024-04-25 04:42 9 浏览 0 评论

在C语言编程中,有许多高级技巧可以帮助我们更好地解决问题,提高代码的效率和可维护性。在本文中, 本人根据工作多年的开发经验总结出平时容易出错的知识点和一些常用的技巧方法, 使初学者少走弯路,避开之前走过的坑路,来提高开发的效率,总结出问题排查的一些方法。

1. 关于变量占位地址大小的问题:

---------------------------例子1-----------------------

(1)以下为Linux下的32位C程序,请计算sizeof的值。

	#include <stdio.h>
	#include <stdlib.h>
	#include <string.h>

	void Func (char str2[100], int size)
	{
		printf (" sizeof (str2):%d.\n", sizeof(str2));
	}

	int main (int argc, char **argv)
	{
		char str1[] = "hello";
		char *p = str1;
		 int  n = 10;
		void *p2 = malloc(100);
		char str2[100] = {0};


		printf ("\n sizeof(str)=%d. \n", sizeof(str1));
		printf (" sizeof(p)=%d.\n", sizeof(p));
		printf (" sizeof(n)=%d.\n", sizeof(n));
		printf (" sizeof(p2)=%d.\n", sizeof(p2));

		Func (str2, 100);

		return 0;
	}	

32位机器输出结果如下:

1) sizeof(str1)= 6 ##字符串5个字符+一个结束符'\0' = 6个字节;

2) sizeof(p)= 4 ##指针变量,大小固定为4个字节;

3) sizeof(n)= 4 ##int类型, 大小固定为4个字节;

4) sizeof(p2)= 4 ##p2也是指针类型,大小为4个字节,指向分配的100个字节首地址;

5) sizeof(str2)= 4 ##str2为形参,也是指针类型,大小固定为4个字节;


64位机器输出结果如下:

1) sizeof(str1)= 6 ##字符串5个字符+一个结束符'\0' = 6个字节;

2) sizeof(p)= 8 ##指针变量,大小固定为8个字节;

3) sizeof(n)= 4 ##int类型, 大小固定为4个字节;

4) sizeof(str2)= 8 ##p2也是指针类型,大小为4个字节

5) sizeof(p2)= 8 ##p2也是指针类型,大小为4个字节


---------------------------例子2-----------------------

(2).Linux下的64位C程序打印值是多少?

	typedef	union
	{
		long i; 
		int k[5];
		char c;
	}Item1;
	
	typedef struct __data{
		int    cat; 
		Item1  cow; 
		double dog;
	} Item2;
	
	
    printf("sizeof item1: %d, sizeof item2: %d.\n", sizeof(Item1), sizeof(Item2));
	
	执行结果:sizeof item1: 24, sizeof item2: 40.

解析:

32位系统一般为4字节对齐,64位系统一般为8字对齐,所以在64位ubuntu系统下结果为:

--Item1是union类型,所有成员变量共用地址空间,要看最大变量所占地址,由于8字节对齐,

k[5]占20个字节,8字节对齐,所以为24个字节;

--Item2是struct 类型,所有成员地址之和,并考虑字节对齐,所以结构体大小为:

4+4(int8字节对齐) + 24(union类型) + 8(double类型为8个字节) = 40

2. 字节对齐问题:

1)结构体对齐规则

<1> 每个数据成员的起始位置必须是自身大小的整数倍;

<2> 结构体总大小必须是结构体成员中最大的对齐模数的整数倍;

<3> 结构体包含数组时,按单个类型对齐方式;

<4> 共用体union取成员的最大内存,但包含在结构体内时,按union内部最大类型字节数的整数倍开始存储; 以下均在32位系统默认4字节对齐的情况下测试:

-----------------------------------例子1-----------------------------------

	struct item_data1
	{
	   char  a;
	   int   b;
	   short c;
	};

结构体大小(32位系统):12个字节

解析:char占一个字节,int占四个字节,由于int的起始地址要在4的倍数上,char后边补齐3个字节,

shor占两个字节,但是整个结构体大小要是最大的对齐模数的整数倍,即4的倍数,所以补两个字节,一共12个字节。

-----------------------------------例子2-----------------------------------

	struct item_data2
	{
		char  a;
		short c;
		int   b;
	};

结构体大小(32位系统):8个字节;

解析:char占一个字节,short占两个字节,由于short的起始地址要在2的倍数上,char后边补齐1个字节;

int占四个字节,刚好在4的倍数上,所以总共8个字节;


-----------------------------------例子3:结构体嵌套结构体-----------------------------------

结构体包含另一个结构体成员,则被包含的结构体成员要从其原始结构体内部的最大对齐模数的整数倍地址开始存储(比如struct a里含有struct b,b中有char、double 、int 元素,那么b应该从8(double)的整数倍开始存储)

	struct item_data3
	{
		char  a;
		struct item_data1 b[2];
		short c;	
	};

结构体大小(32位系统):32个字节;

解析: char占一个字节,char后边补齐3个字节;结构体item_data1占12个字节,2个成员占24个字节;

成员c 占2个字节,后边补齐2个字节,所以总大小为:4+12*2+4 = 32;

-----------------------------------例子4:结构体嵌套union-----------------------------------

结构体包含共用体成员,则该共用体成员要从其原始共用体内部成员中的最大对齐模数的整数倍地址开始存储

	struct item_data4
	{
		char  a;
		union x{
			char m; 
			int  n;
		}  b; 
		short c;	
	};

结构体大小(32位系统):12个字节;

解析: char占一个字节,char后边补齐3个字节;共用体最大为4个字节,成员c为short类型,需要补齐2个字节; 所以总大小为:4+4+4 = 12;


-----------------------------------例子5:结构体包含0数组-----------------------------------

	struct byte2
	{
	   char a;
	   short c;
	   int b;
	   double d[0];
	};

结构体大小(32位系统):8个字节;

解析:

长度为0的数组的作用是为了满足需要可变长度的结构体,具体用法是在一个结构体的最后,申明一个长度为0的数组,就可以使得这个结构体是可变长的。

对于编译器来说,此时长度为0的数组并不占用空间,因为数组名本身不占空间,它只是一个偏移量,数组名这个符号本身代表了一个不可修改的地址常量。


2) 共同体union对齐规则

共同体的内存除了取最大成员内存外,还要保证字节对齐。

	union byte3
	{
		char  a[6];
		short c[5];
		int   b;
	};

共同体byte3中最大成员就是short c[5],占10个字节,由于还要保证字节对齐,所以是10+2=12;


3) 位域字节对齐规则

a. “位域”是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。使用位域的主要目的是压缩存储。 位域列表的形式为: 类型说明符 位域名:位域长度(单位:位 bite)

 如:struct bs
      {
           int a:8;
           int b:2;
           int c:6;
       } data;

其中位域a占8位,位域b占2位,位域c占6位。

b. 位域说明:

<1>. 一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。

<2>. 由于位域不允许跨两个字节,因此位域的长度不能大于一个字节(8位)的长度,也就是说不能超过8位二进位。

<3>. 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如: int :2

c.位域对齐规则:

1) 如果相邻位域字段的类型相同,且其位宽之和小于类型大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;

2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;

3) 如果相邻的位域字段的类型不同,从新的存储单元开始,偏移量为其类型大小的整数倍,即不压缩;

4) 如果位域字段之间穿插着非位域字段,则不进行压缩;

5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。

-----------------------------------例子1----------------------------------

例题:

	(1)typedef struct  AA
	 {
		  unsigned int b1:5;
		  unsigned int b2:5;
		 unsigned int b3:5;
		 unsigned int b4:5;
		 unsigned int b5:5;
     }AA;

sizeof(AA)= 4

【解析】参考规则 1)。

由于相邻成员类型相同,unsigned int为4个字节,b1占5位,b2加上b1的位数之和为10位,不超过4字节,因此b2接着b1继续存储;

同理b3、b4、b5的类型相同,位数之和不超过4字节,因此接着b2继续存储,总位数为25位。

由于结构体的大小是最宽类型成员的整数倍,因此25位之后的补0,直到补满4字节。

-----------------------------------例子2----------------------------------

(2)
     typedef struct  BB
	{
	   unsigned int b1:5;
	   unsigned int b2:5;
	  unsigned int b3:5;
	   unsigned int b4:5;
	   unsigned int b5:5;
	   unsigned int b6:5;
	  unsigned int b7:5;
	}BB;

sizeof(BB)= 8


【解析】参考规则 1) 和规则 2) 。由于相邻成员类型相同,unsigned int为 4 个字节(32位),当存储到 b7 时,b7和b6之前的位数相加超过4字节,因此b7从新的存储单元开始存储。即b1~b6 存储在 第0~29位,第30、31位补0,b7从下一个4字节存储单元 开始存储5位,剩下的补0。


-----------------------------------例子3----------------------------------

(3)

struct test1
{
	char a:1;
	 char :2;
	  long b:3;
	 char c:2;
};

sizeof(test1)= 12

【解析】 

char a:1; //用一个字节去存储

char :2;  //空域。因为与前面的a的类型相同,而两个位域的位宽相加仍然少于8位,所以依然用1个字节表示

long b:3; //long类型的位宽是4个字节,与前面的char类型不同,所以b与a之间偏移4个字节,它们之间自动补充3个字节 

char c:2; //因为c与b又不同型,以test1中的最长的long类型的位宽进行偏移,所以虽然char只用1个字节就够了,但依然要占4个字节。

结构体总长以最长的类型位宽做为偏移量,最长的是long型,占4位,所以不同类型之间应该是4个字节的偏移,即test1应该是4字节的整数倍。 总共是12字节。


3. 指针变量的理解和定义:

	 1) 一个整型数 
		int a;
		例子:
		int a = 100;  //定义变量a,其值为100;
			
	2)一个指向整型数的指针
		int *a;
			
		例子: 
		int val = 100;
		a = &val; //a为一个地址变量,其值为变量val的内存地址;内存地址的值为100;			
			
	3)一个指向指针的的指针,它指向的指针是指向一个整型数 
		int **a;
			
		例子:
		int val = 100;
		int *p = &val;
		a = &p;   //a为地址变量,其值为指针变量p的地址,p的值为变量val的地址;**a = *(*a) = 100; 				
			
	4)一个有10个整型数的数组 
		int a[10]; 			
			
		例子:		
		int a[10] = {1,2,3,4,5,6,7,8,9, 0}; //有10个int类型成员的数组;
			
	5) 一个有10个指针的数组,该指针是指向一个整型数的。 
		int *a[10]; 
			
		例子:
		int *p1, *p2, *p3...., *p10;   //定义了10个整形指针变量;a为10个指针变量的数组(相当于二维数组);
		a[0] = p1;
		a[1] = p2;
		......
		a[9] = p10; 			
			
	6) 一个指向有10个整型数数组的指针 
		int (*a)[10]; 
			
		例子:
		int array1[10], array2[10], array3[10];  
		a = array1;  //a为一个指针变量,指向有10个成员的一维数组;(一维数组指针)
			
	7)一个返回值为指针的函数:
		int *a(int );
			
		例子:
		int *a(int value){  ///a本质是一个函数,返回值为指针的函数;
		    int  *p = (int *)malloc(4); 
		    *p = value;
		   return p;
		}			
			
	8) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数 
		int (*a)(int a); 
			
		例子:
		int function(int val)
		{
			....
		}		
		a = function;   //a为函数指针变量,类型与function函数一致;
		int ret = (*a)(100);  //函数运行;			
			
	9) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数 
		int (*a[10])(int); 
		定义了10个指针函数;
			
		例子:
		int func1(int val)
		{
			....
		}
			
		int func2(int val)
		{
			....
		}
			
		a[0] = func1;    //a为函数指针数组,可以管理多个同类型(如func1一样)的函数;
		a[1] = func2;

		for(int i=0; i<10; i++)
			ret = (*a[i])(100);  //可以使用for循环进行管理,非常方便;

4. 字符串变量相关的地址操作:

(1)分析下列程序的结果:

	--------------------例子1-----------------------------------
	char *s1 = "AAA";
	char s2[] = "BBB"; 
	
	s1[0] = 'B';  //程序崩溃;
	s2[0] = 'C';	
	printf ("s1:%s, s2:%s.\n", s1, s2);	
	

【解析】

(1)s1是一个指针变量,指向一个常量字符串,即“AAA”字符串在代码段,是无法进行修改的;

所以s1没有可写的内存,当进行赋值时,会出现段错误:Segmentation fault (core dumped);

(2)s2是一个数组,初始化为“BBB”,默认已经分配了4个字节的大小,所以可以进行修改操作:s2[0]='C',没问题;

--------------------例子2-----------------------------------


	void getmemory(char *p)
	{
		p=(char *)malloc(100):
		strcpy(p, “hello world”);
	}
	
	int main()
	{
		char*str=NULL;
		getmemory(str);
		printf(“str:%s/n”,str);
		free(str);
		return 0;
	}
	

【解析】

1) 形参中值传递,并不会改变原值的数据。因为原址只是拷贝一份数据传进去,修改的值是拷贝的数据。

2) 指针作为参数,可以传值,但无法传地址;所以指针作为形参,传递的是变量的地址,可以看成是指针变量地址的一份拷贝,函数返回后并没有重新指向新的内存;仍然为空;进入函数后,指针重新指向了一块新分配的内存,但地址已经改变;会产生内存泄露;

3)如果采用双重指针对实现上述功能:

	void getmemory(char **pptr)
	{	
            char *p = NULL;
	    p=(char *)malloc(100):
	    strcpy(p, “hello world”);
				
	    *pptr = p;  //把p对应的地址作为pptr的值传出
	}
       int main()
	{
	       car*str=NULL;   
		getmemory(&str);  、
		printf(“str:%s/n”,str);
		free(str);
		return 0;
	}
 

--------------------例子3-----------------------------------

	  char szstr[10] = {0};
	  strcpy (szstr,"0123456789");  
	  printf ("str:%s.--\n", szstr);

解析:字符串必须要有结尾符号'\0',不然无法识别出来,所以此程序可能会因为地址越界出现打印乱码;

应该定义更大一些的数组szstr[11],另外说明下,strcpy会自动把'\0'一起copy到目的地址;

--------------------例子4----------------------------------

   char aa[10] = {0xFF, 0x0, 'a', 'b','c','d'};
   printf ("size: %d, strlen:%d. \n", sizeof(aa), strlen(aa));
  

【解析】

1)sizeof 计算变量的实际大小,所以sizeof(aa) = 10;

2) strlen 原理是遇到‘\0’或0马上结束,所以上述strlen(aa) = 1;

--------------------例子5-----------------------------------

   void swap_data( int *p1, *p2)
   {
	  int *p;
	  *p = *p1;
	  *p1 = *p2;
	  *p2 = *p;
   }

【解析】

运行结果程序崩溃,原因是定义的p变量为指针类型,但未有分配地址空间,所以*p = *p1,直接赋值会出错;

--------------------例子6-----------------------------------

说明以下变量对应的地址和值是多少?

	#include <stdio.h>
	int main()
	{
		int array[5] = {1, 2, 3, 4, 5}; 

		printf("array = %p, value:%d.\n", array, *(array));
		printf("array + 1 = %p, value:%d.\n", array + 1, *(array+1)));
		printf("array + 2 = %p, value:%d.\n", array + 2, *(array+2)));
		printf("array + 3 = %p, value:%d.\n", array + 3, *(array+3)));
		printf("&array = %p\n", &array);
		printf("&array + 1 = %p\n", &array + 1);
		
		printf ("sizeof(array):%d, sizeof(&array):%d.\n", sizeof(array), sizeof(&array));		
		
		int *ptr = (int *)(&array + 1);
		printf ("*(array+1)=%d, *(ptr-1)=%d \n", *(array+1), *(ptr-1));	
			
		return 0;
	}

【解析】(输出结果):

array = 0x7ffe96cce190, value:1. //以为e190结尾的地址;

array+1 = 0x7ffe96cce194, value:2. //以为e190+4结尾的地址;

array+2 = 0x7ffe96cce198, value:3. //以为e190+8结尾的地址;

array+3 = 0x7ffe96cce19c, value:4. //以为e190+12结尾的地址;

&array = 0x7ffe96cce190 //以为e190结尾的地址

&array + 1 = 0x7ffe96cce1a4

//!!重点:以为e190+20结尾的地址,其中20整个数组的长度大小。

所以,&array + 1 表示:以整个数组大小为单位进行计算操作的;

sizeof(array):20, sizeof(&array):8.

//array是一个数组变量,大小为数组长度;&array是一个指针变量,大小为8个字节(64位系统)

*(array+1)=2, *(ptr-1)=5

//这里注意ptr地址是array+sizeof(array), 所以ptr-1就是指向最后一个数据地址,址为5;

5. 指针与地址转换问题:

--------------------例子1 ---------------------------

      unsigned char *p1 = NULL;
      unsigned long *p2 = NULL;
      unsigned int  address = 0x0801000;

      p1 = (unsigned char *)address;
      p2 = (unsigned long *)address;

      printf ("p1+1: %p, p2+1:%p.\n", p1+1, p2+1);
      printf ("p1+5: %p, p2+5:%p.\n", p1+5, p2+5);

请说明下打印结果的。

【结果】

p1+1: 0x801001, p2+1:0x801008. //char类型占一个字节, long类型占8个字节;

p1+5: 0x801005, p2+5:0x801028.

【解析】

定义不能类型的指针,在进行加减运算时会按指针类型的字节数进行操作。


- -------------------例子2---------------------------

	int array [5] = {1,2,3,4,5};
	int *ptr = (int *)(&array  + 1);
	
	printf ("%d, %d \n", *(array +1), *(ptr-1));

【结果】 2, 5

【解析】 &array + 1 表示:以整个数组大小为单位进行计算操作的;

所以ptr指向地址为:array +sizeof(array ) = array +5,那么 *(ptr-1)即为array [4]的值 ;

-------------------例子3-----------------------------

	void foo(void)
	{
		unsigned int a = 6;
		int b = -20;
		(a+b > 6) ? puts("> 6") : puts("<= 6");
	}

【结果】这个问题测试你是否懂得C语言中的整数自动转换原则。这无符号整型问题的答案是输出是 ">6"。

【解析】 是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。

因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。

这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。

---------------------例子4 -------------------------------

1)如何把地址为 0x100000的内存,赋值为0x1234;

2)如何跳转到地址为 0x100000的函数,并运行;

【解析】

1)(unsigned int*)0x100000 = 0x1234;

2)步骤如下:

---首先要将0x100000强制转换成函数指针即: (void(*)())0x100000

---然后再调用它: *( (void(*)())0x100000) ();


6. 变量自加的问题:

--------------------例子1 ---------------------------

#include <stdio.h>
int main
{
	int a,b,c,d;
	a=10;
	b=a++;  	    //1. a先把值赋给b,然后自加;所以:b=10,a=11; 
	c=++a;			//2. a先自加后,再把值赋给C; 所以:a=12,c=12;
	d=10*a++;		//3. a先乘以10赋给d, 然后a自加;所以:a=13, d=120;
	printf("a, b,c,d: %a, %d,%d,%d", b, c,d);
	return 0; 
}
 	

【结果】a=13, b=10,c=12,d=120


--------------------例子2 ---------------------------

int a = 5, b = 7, c, d;
c = a+++b; 
	

分析:重点是理解运算的优先级,++ 优先级高于+,所以先进行a++运算,再进行+运算;

可看成:c = a++ + b;

【答案】这段代码持行后a = 6, b = 7, c = 12


---------------------例子3 -------------------------------

	 代码如下:
     int b=10;
     printf("1-----(b++, b++): (%d, %d)\n", b++,b++);

     b=10;
     printf("2-----(++b, ++b): (%d, %d)\n", ++b,++b);

     b=10;
     printf("3-----(b++, ++b): (%d, %d)\n", b++,++b);

     b=10;
     printf("4-----(++b, b++): (%d, %d)\n", ++b,b++);

【结果】

1-----(b++, b++): (11, 10)

2-----(++b, ++b): (12, 12)

3-----(b++, ++b): (11, 12)

4-----(++b, b++): (12, 10)

【解析】printf函数参数中的变量是经过压栈和出栈操作的,参数中括号内的表达式是从右向左执行的,输出结果是从左向右的:

1. 先执行右边的b++,因为b++是先赋值保存,后++,所以cpu会记住b的值(即右边打印值已经确定即为10),之后再执行左边的b++,此时 b为11(执行前面b++得到的结果),因为右值++,因此就输出为11,所以结果为11, 10;

2. 先执行右边的++b,因为++b先自加,再调用,而此时cpu并没有到调用它的时候,printf第二个格式化的值对应的数字现在还不确定, 再然后执行++b,同样先自加,再调用的左值运算,即输出12,接着再输出第二个,因为cpu没有记住对第二的调用,他会找当前b的值,当前b的值是12,所以输出12, 12;

3. 先执行右边的++b,之后b=11,同样,第二个打印参数未确定,再执行b++,因为b++是先调用,再自加,所以先输出b,此时b的值是11,再自加,b=12,此时再输出b,因此输出的结果是11,12;

4. 同理分析,右边的b++先执行,由于是右值运算,此时第二个打印值 已经确定,保存下来了,即为10, 再进行左边的++b运算,打印值为12,即得为:12, 10。

(未完待续.....)

相关推荐

Nginx 响应提速10倍,你需要知道的缓存性能优化——FastCGI调优
Nginx 响应提速10倍,你需要知道的缓存性能优化——FastCGI调优

Nginx缓存优化是帮助大家提升网站性能的重要操作之一,proxy_cache主要用于反向代理时,对后端内容源服务器进行缓存;fastcgi_cache主要用于...

2024-05-20 14:44 gowuye

王者荣耀天魔缭乱和逐梦之音返场活动地址 3月22日开启返场活动
王者荣耀天魔缭乱和逐梦之音返场活动地址 3月22日开启返场活动

王者荣耀官方终于确定了天魔缭乱和逐梦之音的返场活动,这让不少小伙伴乐开了花,返场活动将会在3月22日开启,下面就带来王者荣耀天魔缭乱和逐梦之音返场活动地址!王者...

2024-05-20 14:44 gowuye

常见的嵌入式web服务器有哪些?

嵌入式WEB服务器常见的有:Lighttpd,Shttpd,Thttpd,Boa,Mini_httpd,Appweb,Goahead。Lighttpd地址:http://www.light...

简述几款常见的嵌入式web服务器
简述几款常见的嵌入式web服务器

嵌入式web服务器,是web服务器当中的一种,是基于嵌入式系统而实现的web服务器。指的是在嵌入式系统(通俗点就是单片机系统)上实现的一个web服务器,可以通过...

2024-05-20 14:44 gowuye

教你如何利用fastcgi_cache缓存加速WordPress

在使用nginx缓存之前,必须在nginx里面加载专门的模块,这个模块叫做ngx_cache_purge。添加ngx_cache_purge模块下载ngx_cache_purge模块ngx_cache...

扫描WordPress漏洞

检测已知漏洞WPScan是一款广泛使用的WordPress安全扫描工具,它的一项重要功能是检测已知漏洞。在这篇文章中,我们将深入探讨WPScan如何检测已知漏洞,并结合实际示例,帮助读者更好地理解和应...

消灭 Bug!推荐几个给力的开源 Bug 跟踪工具
消灭 Bug!推荐几个给力的开源 Bug 跟踪工具

在这个充满bug的世界里,最遥远的距离不是生与死,而是你亲手制造的bug就在你眼前,你却怎么都找不到它。因此本文准备了7款优秀的开源bug跟踪系...

2024-05-20 14:43 gowuye

生物信息分析入门全攻略

生物信息学是生命科学研究的重大前沿领域,未来将占据生命科学研究的半壁江山。已经有越来越多的小伙伴投入到生物信息的学习中,但是入门难、深入慢、摸不到方向等都成为持续学习的拦路虎。本文根据生物信息技术大牛...

elkb实践经验,再赠送一套复杂的配置文件
elkb实践经验,再赠送一套复杂的配置文件

原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处。宝剑锋从磨砺出,梅花香自苦寒来。诗人白居易,三月下江南,看到沿路开放的桃花,心潮澎湃...

2024-05-20 14:43 gowuye

超详细从0到1 搭建ELK监控
超详细从0到1 搭建ELK监控

监控分类?Metrics用于记录可聚合的数据。例如,1、队列的当前深度可被定义为一个度量值,在元素入队或出队时被更新;HTTP请求个数可被定义为一个计数器,...

2024-05-20 14:42 gowuye

嵌入式开发 之Web配置页面开发
嵌入式开发 之Web配置页面开发

1.PHP是最好的语言??开发动态页面首选的语言是PHP,村村不能在这里忽悠人,如果你的硬件性能允许切略懂PHP,看到这里就可以退出了。本文面向的受众是Linu...

2024-05-20 14:42 gowuye

Python开发一个网站目录扫描工具用来检测网站是否有漏洞?
Python开发一个网站目录扫描工具用来检测网站是否有漏洞?

开发一个网站目录扫描工具是用来检测网站是否有非法目录请求的一个常见需求之一,我们要通过这个扫描工具来找到通过某个域名可以访问到的网站路径,可能对于有些系统来讲,...

2024-05-20 14:42 gowuye

创建一个类似Youtube的Id——使用PHP/Python/JS/Java/SQL

id通常都是用数字,不巧的是只有10个数字来使用,所以如果你有很多的记录,id往往变得非常冗长。当然对于计算机来说无所谓,但我们更希望id尽可能短。所以我们如何能使id变短?我们可以利用字母让它们附加...

快速云:有助于移动应用安全开发的五条妙计
快速云:有助于移动应用安全开发的五条妙计

许多企业不断地向其开发团队提供培训。但是某些漏洞,如早在十多年前就发现的SQL注入,如今仍广泛存在于各种应用中。因而,安全培训永不过时。在开发移动应用时,开发者...

2024-05-20 14:41 gowuye

洛杉矶国际电影节最佳动画短片奖影片《G’DAY》正式全网上映
洛杉矶国际电影节最佳动画短片奖影片《G’DAY》正式全网上映

7月2日,由M&CSaatchi创作,由深受好评的澳大利亚导演迈克尔·格雷西执导的动画短片《G’day》,正式在全网上映。该影片因其出色的创意赢得了洛...

2024-05-20 14:41 gowuye

取消回复欢迎 发表评论: