C程序设计语言--第五章:指针与数组

为什么80%的码农都做不了架构师?>>>   hot3.png

指针是一种保存变量地址的变量.

5.1 指针与地址

通常的机器都有一系列连续编号或编址的存储单元,这些存储单元可以单个进行操纵,也可以连续成组的方式操纵.指针是能够存放一个地址的一组存储单元(通常是两个或四个字节).

一元运算符&可用于取一个对象的地址.

p = &c;
将把c的地址赋值给变量p,我们称p为"指向"c的指针.地址运算符&只能应用于内存中的对象,即变量与数组元素.它不能作用域表达式,常量或register类型的变量.

但是,如果我们非要读取地址100上的数据呢?则可以用void *来显式的声明指针进行赋值.

#include <stdio.h>int main(void)
{int *p = ( void * )100;printf("%d\n", p );printf("%d\n", *p );return 0;
}
p的值为100,但是*p的值却是未定义的.

一元运算符*是间接寻址或间接引用运算符.当它作用于指针时,将访问指针所指向的对象.

int x = 1;
int y = 2; 
int z[ 10 ];
int *ip = NULL;ip = &x;		/* ip现在指向x */
y = *ip;		/* y的值现在为1 */
*ip = 0;		/* x的值现在为0 */
ip = &z[ 0 ];	        /* ip现在指向z[ 0 ]*/
我们应该注意:指针只能指向某种特定类型的对象,也就是说,每个指针都必须指向某种特定类型的数据类型(一个例外的情况是指向void类型的指针可以存放指向任何类型的指针,但它不能间接引用其自身.)

如果iq,ip均是指向int的指针,那么

iq = ip;
将把ip中的值拷贝到iq中,这样,指针iq也将指向ip指向的对象.这种方法通常用于建立临时变量iq来代替ip进行运算.

5.2 指针与函数参数

由于C语言是以传值的方式将参数值传递给被调用函数,因此,被调用函数不能直接修改主调用函数中变量的值.但是,如果我们把变量的地址传递进去,无法修改地址的情况下修改地址上存储的变量的值,则可以达到类似修改了参数值的效果.

下列swap函数无任何效果:

void swap( int x, int y )
{int temp = x;x = y;y = temp;
}
但是,我们声明参数为指针,则可以达到效果:
void swap( int *px, int *py )
{int temp = *px;*px = *py;*py = temp;
}
书上有个例子,读取输入流中的数字,但是并不通用,因为你会发现:当输入流中加入一个非空格或者数字的字符(比如字母)的时候,那么程序就这样死循环了----因为它会不断的getch这个字母,ungetch这个字母:
#include <ctype.h>
#include <stdio.h>#define SIZE 128
char buffer[ SIZE ];
int	index;int getch( void )
{return index > 0 ? buffer[ --index ] : getchar();
}
void ungetch( int iValue)
{if ( index >= SIZE ){printf("error: buffer is full\n");}else{buffer[ index++ ] = iValue;}
}int getint( int *pn )
{int c, sign;while ( isspace( c = getch() ) ){;}if ( !isdigit( c ) && c != EOF && c != '+' && c != '-' ){ungetch( c );return 0;}sign = ( c == '-' ) ? -1 : 1;if ( c == '+' || c == '-' ){c = getch();}for ( *pn = 0; isdigit( c ); c = getch() ){*pn = 10 * *pn + ( c - '0' );}*pn *= sign;if ( c != EOF ){ungetch( c );}return c;
}int main(void)
{int n;int array[10];for ( n = 0; n < 10 && getint( &array[ n ] ) != EOF; n++ );for ( n = 0; n < 10; n++ ){printf("%d--", array[ n ] );}return 0;
}
程序输出:

习题5-1:

对于此习题,个人并不推荐将'+'或者'-'写回到输入流中,而是应该用某种技巧忽略非数字的符号来达到目的,否则当写回输入流后,会导致数组的n位置变成了垃圾值:

#include <ctype.h>
#include <stdio.h>#define SIZE 128
char buffer[ SIZE ];
int	index;int getch( void )
{return index > 0 ? buffer[ --index ] : getchar();
}
void ungetch( int iValue)
{if ( index >= SIZE ){printf("error: buffer is full\n");}else{buffer[ index++ ] = iValue;}
}int getint( int *pn )
{int c, sign;while ( isspace( c = getch() ) ){;}if ( !isdigit( c ) && c != EOF && c != '+' && c != '-' ){ungetch( c );return 0;}sign = ( c == '-' ) ? -1 : 1;if ( c == '+' || c == '-' ){int temp = c;c = getch();if ( !isdigit( c ) ){ungetch( temp );return 0;}}for ( *pn = 0; isdigit( c ); c = getch() ){*pn = 10 * *pn + ( c - '0' );}*pn *= sign;if ( c != EOF ){ungetch( c );}return c;
}int main(void)
{int n;int array[10];for ( n = 0; n < 10 && getint( &array[ n ] ) != EOF; n++ );for ( n = 0; n < 10; n++ ){printf("%4d\n", array[ n ] );}return 0;
}
程序输出:

即途中的a,b,c,d均占用了数组的一个元素空间.我们可以简单的忽略掉这些字母:

将if判断换成while判断即可:

if ( c == '+' || c == '-' ){c = getch();while ( !isdigit( c ) ){c = getch();}
}
则程序输出:

习题5-2:

对于习题5-2,我们进行改进,即将输入的字符串中的浮点数提取出来,并将其一一输出:

#include <stdio.h>
#include <ctype.h>
#include <math.h>void showFloatNumber( char *line )
{char	*str = line;char	*temp = str;while ( '\n' != *line ){while ( !isdigit( *line ) ){line++;}while ( isdigit( *line ) || '.' == *line ){*str++ = *line++;}*str = '\0';str = temp;printf("%f\n", atof( str ) );}
}int main(void)
{char buf[128];while ( NULL != fgets( buf, 128, stdin ) ){showFloatNumber( buf );}return 0;
}
从这里可以看出,指针的作用真的非常的强大.程序输出:

5.3 指针与数组

pa为数组,则

pa[ i ]<==>*( pa + i )
简而言之,一个通过数组和下标实现的表达式可等价的通过指针和偏移量实现.

但是,数组名和指针之间有一个不同之处:指针是一个变量.因此,在C语言中,语句pa = a和pa++都是合法的.但数组名不是变量,因此,类似于a = pa和a++形式的语句是非法的.

当把数组名传递给一个函数时,实际上传递的是该数组第一个元素的地址.在被调用函数中,该参数是一个局部变量,因此,数组名参数必须是一个指针,也就是一个存储地址值的变量.

#include <stdio.h>char* my_strlen( char *s )
{int n;for ( n = 0; *s != '\0'; s++ ){n++;}return s;
}int main(void)
{char arr[] = "hello";printf("%s\n", my_strlen( arr ) );printf("%s\n", arr );return 0;
}
函数进行操作的s的副本,故这段程序输出的是:

注意:第一个输出为空('\0');

我们不能改变my_strlen中s的地址!!!所以s++并为对实参s有任何的影响,但我们可以改变其内容:

#include <stdio.h>char* my_strlen( char *s )
{char *temp = s;while ( '\0' != *s ){*s++ = 'h';}*s = '\0';s = temp;return s;
}int main(void)
{char arr[] = "hello";printf("%s\n", my_strlen( arr ) );printf("%s\n", arr );return 0;
}
程序输出:

来对"我们不能改变s的地址"做个解释:这里不是说改变就有错误,而是你改变s的地址,改的是副本的地址,而不是原来实参的地址:

#include <stdio.h>//char arr[] = "world";
char* my_strlen( char *s )
{char arr[] = "world";char *p = arr;s = p;return s;
}int main(void)
{char arr[] = "hello";printf("%s\n", my_strlen( arr ) );printf("%s\n", arr );return 0;
}
程序输出:

之所以第一个字符串为乱码是因为s指向的是一个临时的局部变量,当程序从函数中返回的时候,这个局部变量已经销毁了....

5.4 地址算术运算

我们来编写类似于malloc和free的堆栈版本alloc和afree函数,进行地址算术运算的讨论:

#define ALLOCSIZE	10000static char allocbuf[ ALLOCSIZE ];static char *allocp = allocbuf;char *alloc( int n )
{if ( allocbuf + ALLOCSIZE - allocp >= n ){allocp += n;return allocp - n;}return 0;
}void afree( char *p )
{if ( p >= allocbuf && p < allocbuf + ALLOCSIZE ){allocp = p;}
}
指针与整数之间不能相互转换,但0是例外:常量0可以赋值给指针,指针也可以和常量0进行比较.但是,指向不同数组的元素的指针之间的算术或比较运算没有定义(这里有个特例:指针的算术运算中可使用数组最后一个元素的下一个元素的地址).

我们可以通过指针的地址运算来改写strlen函数:

int strlen( char *s )
{char *p = s;while ( '\0' != *p ){p++;}return p - s;
}
这里要注意:p最后的值是'\0',所以只要返回p - s, 而不是返回p - s + 1.

有效的指针运算包括相同类型指针之间的赋值运算:指针同整数之间的加法或减法运算:指向相同数组中元素的两个指针间的减法或比较运算;将指针赋值为0或指针与0之间的比较运算.其他所有形式的指针运算都是非法的,例如两个指针间的加法,乘法,出发,移位或屏蔽运算;指针同float或double类型之间的加法运算;不经强制类型转换而直接将指向一种类型对象的指针赋值给指向另一种类型对象的指针的运算(两个指针之一是void *类型的情况除外).

5.5 字符指针与函数

字符串常量是一个字符数组.例如:

"I am a string"
在字符串的内部表示中,字符数组以空字符'\0'结尾.字符串常量可通过一个指向其第一个元素的指针访问.
char *pmessage;
pmessage = "now is the time";
将把一个指向字符数组的指针赋值给pmessage.该过程并没有进行字符串的复制,而只是涉及到指针的操作.C语言没有提供将整个字符串作为一个整体进行处理的运算符.

下面两个定义之间有很大的差别:

char amessage[] = "hello world";/*定义一个数组*/
char *pmessage = "hello world";/*定义一个指针*/
上述声明中,amessage是一个仅仅足以存放初始化字符串以及空字符'\0'的一维数组.数组中的单字符可以进行修改,但amessage始终指向一个存储位置.另一方面,pmessage是一个指针,其初值指向一个字符串常量,之后它可以被修改以指向其他地址.但如果试图修改字符串的内存,结果是没有定义的.
#include <stdio.h>int main(void)
{char amessage[] = "hello world";char *pmessage = "hello world";amessage[ 2 ] = 'm';pmessage[ 2 ] = 'm';printf("%s\n", amessage );printf("%s\n", pmessage );return 0;
}
程序出现未定义行为,因为pmessage[ 2 ] = 'm'本身是未定义的.

以下两个有用的函数来讨论数组和指针方面的关联:

strcpy数组的实现:

void strcpy( char *s, char *t )
{int i;i = 0;while ( ( s[ i ] = t[ i ] ) != '\0' ){i++;}
}
指针实现:
void strcpy( char *s, char *t )
{while ( *s++ = *t++ );
}
strcmp数组的实现:
int strcmp( char *s, char *t )
{int i;for ( i = 0; s[ i ] == t[ i ]; i++ ){if ( '\0' != s[ i ] ){return 0;}}return s[ i ] - t[ i ];
}
指针实现:
int strcmp( char *s, char *t )
{for ( ; *s == *t; s++, t++ ){if ( '\0' == *s ){return 0;}}return *s - *t;
}
这里不能将for循环改写为:
while ( *s++ == *t++ )
是因为当寻找到不相等的元素的时候,自增操作导致return回去的是不相等字符的下一个元素之差.

习题5-3:

void strcat( char *s, char *t )
{while ( '\0' != *s ){s++;}while ( *s++ = *t++ ){;}
}
习题5-4:
int strend( char *s, char *t )
{char *temp = t;while ( '\0' != *s ){s++;}while ( '\0' != *t ){t++;}while ( temp <= t ){if ( *t != *s ){return 0;}t--;s--;}return 1;
}
习题5-5:
#include <stdio.h>void strncpy( char *s, char *t, int n )
{while ( n-- && ( *s++ = *t++ ) )		//&&的优先级高于=,所以要加上括号;*s = '\0';
}void strncat( char *s, char *t, int n )
{while ( '\0' != *s ){s++;}while ( ( *s++ = *t++ ) && n-- );*s = '\0';
}int strncmp( char *s, char *t, int n )
{for ( ; ( *s == *t ) && n--; s++, t++ ){if ( '\0' != *s ){return 0;}}return *s - *t;
}int main(void)
{char s[128] = "hello";char t[] = "helld";strncpy( s, t, 4 );printf("%s\n", s );strncat( s, t, 5 );printf("%s\n", s );printf("%d\n", strncmp( s, t, 3 ) );return 0;
}
程序输出:

习题5-6:

getline函数:

int getline( char *s, int lim )
{int ch;char *temp = s;while ( --lim > 0 && ( ch = getchar() ) != EOF && ch != '\n' ){*s++ = ch;}if ( '\n' == ch ){*s++ = ch;}*s = '\0';return s - temp;
}
atoi函数:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>int my_atoi( char *s )
{int n = 0;int sign = 1;while ( isspace( *s ) ){s++;}if ( '-' == *s || '+' == *s ){sign = ( '-' == *s ) ? -1 : 1;s++;}while ( isdigit( *s ) ){n = 10 * n + ( *s - '0' );s++;}return sign * n;
}
int main(void)
{printf("%d\n", my_atoi("-12345") );return 0;
}
程序输出:

itoa函数 + reverse函数:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>void reverse( char *s )
{char *temp = s;while ( '\0' != *temp ){temp++;}temp--;while ( s < temp ){char ch = *s;*s++ = *temp;*temp-- = ch;}
}void my_itoa( int n, char *s )
{char *temp = s;int sign = 0;if ( n < 0 ){n = -n;sign = 1;}while ( n / 10 ){*temp++ = n % 10 + '0';n /= 10;}*temp++ = n + '0';if ( sign ){*temp++ = '-';}*temp = '\0';reverse( s );
}int main(void)
{char str[128];my_itoa( -12345, str );printf("%s\n", str );return 0;
}
程序输出:

strindex函数:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>int strindex( char *s, char *t )
{char *tempForS = s;char *tempForT = t;int len = strlen( t );while ( '\0' != *s ){while ( *t == *s ){t++;s++;}if ( '\0' == *t ){return s - tempForS - len;}if ( '\0' == *s ){return -1;}s++;t = tempForT;}return -1;
}int main(void)
{char str[] = "hello world i love this world";char dst[] = "this";printf("%d\n", strindex( str, dst ) );return 0;
}
程序输出:

getop函数:

int getop( char *s )
{int c;while ( ( *s = c = getch() ) == ' ' || c == '\t' );s++;*s = '\0';if ( !isdigit( c ) && c != '.' ){return c;}if ( isdigit( c ) ){while ( isdigit( *s = c = getch() ) ){s++;}}if ( '.' == c ){while ( isdigit( *s = c = getch() ) ){s++;}}*s = '\0';if ( c != EOF ){ungetch( c );}return NUMBER;
}
5.6 指针数组以及指向指针的指针
#include <stdio.h>
#include <string.h>#define MAXLINES 5000char *lineptr[ MAXLINES ];int readlines( char *lineptr[], int nlines );
void writelines( char *lineptr[], int nlines );void qsort( char *lineptr[], int left, int right );int main(void)
{int nlines;if ( ( nlines = readlines( lineptr, MAXLINES ) ) >= 0 ){qsort( lineptr, 0, nlines - 1 );writelines( lineptr, nlines );return 0;}else{printf("error: input too big to sort\n");return 1;}
}#define MAXLEN 1000
int getline( char *, int );
char *alloc( int );int readlines( char *lineptr[], int maxlines )
{int len, nlines;char *p, line[ MAXLEN ];nlines = 0;while ( ( len = getline( line, MAXLEN ) ) > 0 ){if ( nlines >= maxlines || ( p = alloc( len ) ) == NULL ){return -1;}else{line[ len - 1 ] = '\0';strcpy( p, line );lineptr[ nlines++ ] = p;}}return nlines;
}void writelines( char *lineptr[], int nlines )
{while ( nlines-- > 0 ){printf("%s\n", *lineptr++ );}
}void qsort( char *v[], int left, int right )
{int i, last;void swap( char *v[], int i, int j );if (left >= right ){return;}swap( v, left, ( left + right ) / 2 );last = left;for ( i = left + 1; i <= right; i++ ){if ( strcmp( v[ i ], v[ left ] ) < 0 ){swap( v, ++last, i );}}swap( v, left, last );qsort( v, left, last - 1 );qsort( v, last + 1, right );
}void swap( char *v[], int i, int j )
{char *temp;temp = v[ i ];v[ i ] = v[ j ];v[ j ] = temp;
}
5.7 多维数组

我们考虑一个日期转换的问题:把某月某日这种日期表示形式转换为某年中的第几天的表示形式,反之亦然.

习题5-8:

static char daytab[ 2 ][ 13 ] = {{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31,30, 31},{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31,30, 31}
};
int day_of_year( int year, int month, int day )
{if ( year <= 0 || month < 1 || month > 12 || day < 0 || day > 31 ){return -1;}int i, leap;leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0;for ( i = 1; i < month; i++ ){day += daytab[ leap ][ i ];}return day;
}void month_day( int year, int yearday, int *pmonth, int *pday )
{int i, leap;leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0;if ( leap && yearday > 366 ){return;}else if ( yearday > 365 ){return;}for ( i = 1; yearday > daytab[ leap ][ i ]; i++ ){yearday -= daytab[ leap ][ i ];}*pmonth = i;*pday = yearday;
}
5.8 指针数组的初始化
char *month_name( int n )
{static char *name[] = {"Illegal month","January", "February", "March","April", "May", "June","July", "August", "September", "October", "November", "December"};return ( n < 1 || n > 12 ) ? name[ 0 ] : name[ n ];
}
5.9 指针与多维数组

习题5-9:

static char daytab[ 2 ][ 13 ] = {{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31,30, 31},{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31,30, 31}
};
int day_of_year( int year, int month, int day )
{int i, leap;char *p;leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0;p = daytab[ leap ];while ( --month ){day += *++p;}return day;
}void month_day( int year, int yearday, int *pmonth, int *pday )
{int i, leap;char *p;leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0;p = daytab[ leap ];while ( yearday > *++p ){yearday -= *p;}*pmonth = p - *( daytab + leap );*pday = yearday;
}int main(void)
{int month;int day;int newday = day_of_year( 2013, 10, 1 );month_day( 2013, newday, &month, &day );printf("%d--%d\n", month, day );return 0;
}
程序输出:

5.10 命令行参数

调用主函数main时,它带有两个参数.第一个参数argc的值表示运行程序时命令行中参数的数目;第二个参数argv是一个指向字符串数组的指针,其中每个字符串对应一个参数.且ANSI标准要求argv[ argc ]的值必须为一个空指针.

程序echo的作用是将命令行参数进行回显.比如我们输入echo hello, world 则打印出hello, world

程序echo的第一个版本将argv看成是一个字符指针数组:

#include <stdio.h>int main( int argc, char *argv[] )
{int i;for ( i = 1; i < argc; i++ ){printf("%s%s", argv[ i ], ( i < argc - 1 ) ? " " : "" );}printf("\n");return 0;
}
第二个版本则是指针的指针:
#include <stdio.h>int main( int argc, char *argv[] )
{while ( --argc > 0 ){printf("%s%s", *++argv, ( argc > 1 ) ? " " : "" );}printf("\n");return 0;
}
习题5-10:
#include <stdio.h>int main(int argc, char *argv[] )
{int buf[ 128 ];int index = -1;int result;int i;for ( index = 0; index < 128; index++ ){buf[ index ] = 0;}index = -1;while ( --argc > 0 ){++argv;if ( '+' == ( *argv )[ 0 ] ){//我不知道为什么不能用"+" == *argv进行比较result = buf[ index ];index--;buf[ index ] += result;}else if ( '-' == ( *argv )[ 0 ] ){result = buf[ index ];index--;buf[ index ] -= result;}else if ( '*' == ( *argv )[ 0 ] ){result = buf[ index ];index--;buf[ index ] *= result;}else if ( '/' == ( *argv )[ 0 ] ){result = buf[ index ];if ( 0 == result ){printf("error: zero to divisor\n");break;}index--;buf[ index ] /= result;}else{buf[ ++index ] = atoi( *argv );}}printf("%d\n", buf[ 0 ] );return 0;
}
程序输出:

习题5-11:

信心被一点一点击垮了.....根本不知道如何下手..........



转载于:https://my.oschina.net/voler/blog/165515

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/265554.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java list 自定义类型转换_使用Java Stream API将List按自定义分组规则转换成Map的一个例子...

本文完整测试代码见文末。测试数据是List里的4个员工对象实例&#xff1a;根据员工所在的城市进行分组&#xff1a;结果分成了三组&#xff1a;第一组的员工在上海&#xff1a;第二组的员工在成都&#xff1a;统计每组员工个数&#xff1a;把员工进行分组&#xff0c;得分大于1…

安卓app与阿里云服务器的无线通信(非局域网)

参考&#xff1a;安卓app与阿里云服务器的无线通信&#xff08;非局域网&#xff09; 作者&#xff1a;图触靓 发布时间&#xff1a; 2020-08-01 16:13:14 网址&#xff1a;https://blog.csdn.net/bhbhhyg/article/details/107732156 目录写在阿里云里面的服务器代码&#xff1…

10.继承和派生

2019独角兽企业重金招聘Python工程师标准>>> 类成员访问权限&#xff1a; 成员访问权限&#xff1a;私有成员&#xff1a;只能被类自身的成员和友元访问&#xff1b; 公有成员&#xff1a;可以被任何普通函数和任何类的成员函数或子类访问&#xff1b; 保护成员&a…

树莓派与阿里云服务器之间的无线通信(非局域网)

参考&#xff1a;Linux虚拟机sqlite数据库安装教程 作者&#xff1a;图触靓 发布时间&#xff1a; 2020-08-01 15:45:026 网址&#xff1a;https://blog.csdn.net/bhbhhyg/article/details/107731166 购买服务器后。我们可以点击控制台&#xff0c;找到实例列表&#xff0c;点击…

业余剪辑——从拍摄到剪辑到加字幕

工作需要帮公司做一个公司的宣传片&#xff0c;要求不是很高所以就让我这个半吊子“设计”来做视频了。。。 以下设备和软件的使用只是我个人本次的使用的记录&#xff0c;大家按需使用即可 一、拍摄 设备&#xff1a;手机 软件&#xff1a;剪辑大师app&#xff08;应用商店下载…

树莓派作为客户端与WemosD1作为服务器的无线通信(局域网通信)

参考&#xff1a;树莓派作为客户端与WemosD1作为服务器的无线通信&#xff08;局域网通信&#xff09; 作者&#xff1a;图触靓 发布时间&#xff1a; 2020-07-26 21:50:39 网址&#xff1a;https://blog.csdn.net/bhbhhyg/article/details/107599915 目录wemos版作为服务端代码…

Lync Server的环境搭建(五):Lync-Server的安装部署

今天,我们接着来进行Lync-Server服务端的安装。我们分别打开“Lync-DC”和“Lync-Server”这两台虚拟机&#xff0c;切换到“Lync-Server”下&#xff0c;“开始”—“Lync Server安装部署&#xff0c;单击“安装或更新Lync Server系统”。弹出”部署向导“窗口&#xff0c;我们…

NodeMan介绍

近年来&#xff0c;随着nodejs的突飞猛进&#xff0c;node项目数量增长迅猛&#xff0c;node项目完美的阐释了“开箱即用”的理念。小到创业公司&#xff0c;大到阿里这样的巨头&#xff0c;背后均有node的身影。 node项目基于Chrome的V8引擎&#xff0c;使用JavaScript&#x…

#ifndef, #define, #endif的作用

目录作用示例作用 #ifndef 它是if not define 的简写&#xff0c;是宏定义的一种&#xff0c;实际上确切的说&#xff0c;这应该是预处理功能三种&#xff08;宏定义、文件包含、条件编译&#xff09;中的一种——条件编译。 在c语言中&#xff0c;对同一个变量或者函数进行…

高性能的MySQL(2)慢查询

一、剖析MySQL查询1、首先从慢查询开始&#xff0c;慢查询是开销最低&#xff0c;精度最高的测量查询时间的工具。a、开始mysql的慢查询&#xff0c;修改my.conf[mysqld] #开启慢查询 log_slow_queries ON #指定日志文件存放位置&#xff0c;可以为空&#xff0c;系统会给一个…

python爬虫获取小说根据正文调用函数传入章节地址列表_python爬虫之小说章节获取,聊斋志异小说完整版...

“写鬼写妖高人一等&#xff0c;刺贪刺虐入骨三分。”没找到聊斋志异完整版的txt文档&#xff0c;那就把在线阅读的文章抓下来吧。开发环境python3.7requests模块lxml模块获取分析找到聊斋志异的小说网站。通过查看源码与分析小说每一章的URL链接发现&#xff0c;构成每一章的U…

程序运行时对应的内存分布(BSS段、数据段、代码段、堆、栈)关系

参考&#xff1a;程序运行时对应的内存分布关系 作者&#xff1a;嵌入式基地&#xff08;公众号&#xff09; 发布时间&#xff1a; 2021-04-28 网址&#xff1a;https://mp.weixin.qq.com/s/AVDPZawSjg9HtxEm8vsFBA 参考&#xff1a;静态变量与动态变量的定义与区别 作者&…

java线程池 锁_java多线程——锁

这是多线程系列第四篇&#xff0c;其他请关注以下&#xff1a;如果你看过前面几篇关于线程的文字&#xff0c;会对线程的实现原理了然于胸&#xff0c;有了理论的支持会对实践有更好的指导&#xff0c;那么本篇会偏重于线程的实践&#xff0c;对线程的几种应用做个简要的介绍。…

Ubuntu时间显示不准确的解决方案

参考&#xff1a;解决ubuntu里面时间不正确的办法 作者&#xff1a;三速何时sub20 发布时间&#xff1a;2020-12-08 16:24:27 网址&#xff1a;https://blog.csdn.net/weixin_44234294/article/details/110875899?spm1001.2014.3001.5501 目录1、进入终端2、输入命令3、选择 A…

Ubuntu下软件的安装、卸载方法

参考&#xff1a;Ubuntu 如何使用命令卸载安装过的软件&#xff08;超级简单&#xff09; 作者&#xff1a;一只青木呀 发布时间&#xff1a;2020-08-04 09:19:01 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/107778981 参考&#xff1a;Ubuntu下软…

Ubuntu文件压缩、解压缩、打包解包(带软链接)、拷贝文件(带软链接)、拷贝文件夹

参考&#xff1a;Ubuntu 命令解压文件大全 作者&#xff1a;一只青木呀 发布时间&#xff1a; 2020-08-04 17:18:55 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/107791294 参考&#xff1a;打包和压缩的概念和区别 作者&#xff1a;不浪漫的罪名L…

Ubuntu开启FTP服务方法(Ubuntu和Windows之间互传文件需要开启——服务器端)

目录Ubuntu开启FTP服务步骤&#xff1a;Ubuntu开启FTP服务步骤&#xff1a; 工作中Ubuntu和Windows之间互传文件&#xff0c;需要服务器端&#xff08;Ubuntu&#xff09;开启FTP服务&#xff0c;客户端&#xff08;Windows&#xff09;安装FileZilla。平时自己学习电脑安装虚拟…

win7共享wifi

为什么80%的码农都做不了架构师&#xff1f;>>> 1.从开始菜单找到“命令提示符”&#xff0c;或直接键入cmd快速搜索&#xff0c;右键单击它&#xff0c;选择“以管理员身份运行” 2.运行以下命令启用虚拟无线网卡&#xff1a; netsh wlan set hostednetwork mod…

Ubuntu开启NFS、SSH服务(驱动开发用到、电脑端登录ARM板用到)

参考&#xff1a;Ubuntu下NFS服务的开启 作者&#xff1a;一只青木呀 发布时间&#xff1a;2020-08-04 14:06:58 网址&#xff1a;https://blog.csdn.net/weixin_45309916/article/details/107784877 目录NFS服务的开启1.安装NFS服务2.创建 linux 工作目录3.配置NFSUbuntu下SSH…