• C语言汇总


    汇总一(linux环境)

    /bin :bin是二进制(binary)英文缩写。

    /boot:存放的都是系统启动时要用到的程序。
    /dev:包含了所有Linux系统中使用的外部设备。
    /etc:存放了系统管理时要用到的各种配置文件和子目录。
    /lib:存放系统动态连接共享库的。
    /home:管理普通用户的主目录
    /root:根用户(超级用户)的主目录

    1. 1. ~ 家目录符号
    2. 2. / 根目录符号
    3. 3. $ 普通用户
    4. 4. # 超级用户

    汇总二(数据)

    void类型大小为1个字节

    1. '\0'---0
    2. '\n'---10
    3. ' ' ---32 (这是个空格)
    4. ......
    5. '0' ---48 (差48
    6. '1' ---49
    7. ......
    8. 'A' ---65
    9. 'B' ---66
    10. ......
    11. 'a' ---97 (差32
    12. 'b' ---98

    1.char

    char 与 unsigned char (1字节)    2^8=256
    char 数值范围:,-128~127
    unsigned char 数值范围:0 ~256

    若存储char类型 129,由于补码的存在,CPU读取的是补码,编译成功后,输出-127

    若存储unsigned char 类型 -1 ,输出255

    补码:1111 1111

    反码:1111 1110

    源码:1000 0001

    float4字节、double 8字节

    汇总三(常量、变量)

    1.常量

    1.整型常量2.字符常量3.字符串常量4.浮点常量

    2.变量:

    定义:

    <存储类型> <数据类型> <变量名>;

    存储类型:1.自动:auto(可以不写)2.静态:static

                         3.寄存器:register4.外部:extern(静态存储)

    数据类型:

    1.字符变量

    1. //1. 定义
    2. char a;
    3. //2. 定义并初始化
    4. char a = 'a';
    5. //3. 赋值
    6. a = 'b';

    2.整型变量

    1. //1. 定义
    2. short a;
    3. int b;
    4. long c;
    5. //2. 定义并初始化
    6. int b = 5;
    7. //3. 赋值
    8. b = 1;

    3.浮点变量

    1. //1. 定义
    2. float a;
    3. double b;
    4. //2. 定义并初始化
    5. float c = 5.5;
    6. //3. 赋值
    7. c = 1.1;

    局部变量、全局变量、静态变量、外部变量

    1.作用域:能使用的范围限制
    1. #include <stdio.h>
    2. int main(int argc, const char *argv[])
    3. {
    4. {
    5. int a=10;
    6. printf("in a=%d\n", a);
    7. }
    8. /*作用域*/
    9. //printf("out a=%d\n", a);
    10. return 0;
    11. }
    12. 花括号内为一个语句块

    .花括号内为一个语句段。

    2.时间周期:能使用的时间限制

    结论:两次调用的函数中,变量b使用的空间不同,第一次调用后b的空间会释放掉,第二次会重新申请空间,所以两次打印b的值不同。

    3.局部变量和全局变量
    1. #include <stdio.h>
    2. /*全局变量*/
    3. int a=10;
    4. int main(int argc, const char *argv[])
    5. {
    6. {
    7. /*局部变量*/
    8. int b=20;
    9. printf("a=%d\n", a);
    10. printf("b=%d\n", b);
    11. }
    12. //printf("a=%d\n", a);
    13. //printf("b=%d\n", b);
    14. return 0;
    15. }

    局部变量存储与栈中,全局变量存在于静态存储区

    4.静态变量和外部变量
    静态变量
    1. #include
    2. void fun(void)
    3. {
    4. //在程序执行期间,只申请一次空间
    5. static int b = 1;
    6. printf("b=%d\n", b);
    7. b = 2;
    8. //函数结束,静态变量不释放
    9. }
    10. int main(int argc, const char *argv[])
    11. {
    12. fun();
    13. fun();
    14. return 0;
    15. //程序结束,静态变量释放
    16. }

    输出结果为 b=1  b=2

    说明b为同一个,使用的是同一块地址空间,第二次调用函数时,不在申请新地址去存b。main函数结束时静态存储区才释放。

    加上static从原来的栈中存放改为静态存储区,整个程序执行期间都有不销毁。改变了生命周期

    静态区:

    1.常量2.静态变量3.静态局部变量4.全局变量

    auto类型的 局部变量存储于栈之中

    全局变量存储于静态空间区

    程序结束,静态存储区内容才释放。

    外部变量
    1. A.c
    2. int global_a = 100;
    3. //static int global_a = 100;
    4. B.c
    5. #include <stdio.h>
    6. extern int global_a;
    7. int main(int argc, char *argv[])
    8. {
    9. //int global_a;
    10. printf("global_a=%d\n", global_a);
    11. return 0;
    12. }
    13. 注意: extern声明的是定义过的全局变量(静态存储区),所以extern的变量是静态存储区(内存管理)
    14. 提醒:起名字要遵守语法规范,且要见名知意,尽量使用英文单词格式。
    15. gcc A.c B.c -o out

    若B.c中global_a前没写extern,同样会打印出结果。因为int global_a = 100;是全局变量存储于静态区,同样会执行,但是还是要申请,因为此文件中其他同名变量可能会赋值

    注意: extern声明的是定义过的全局变量(静态存储区),所以extern的变量是静态存储区(内存管理)提醒:起名字要遵守语法规范,且要见名知意,尽量使用英文单词格式。
     

    全局变量和局部变量同名的话,采用就近原则

    汇总四(内存管理)

    1.内存管理

    数据区:这一块的内存在程序编译时就已经分配好,在程序整个运行期间都存在。属于静态内存分配。
    栈:自动局部变量,系统分配的内存,向下增长
    堆:程序员主动申请的、动态分配的内存,向上增长。(malloc、free)

    2.自动局部变量和静态局部变量

    (auto)自动局部变量:栈区;生命周期是当前语句块、函数,作用域是当前语句块、函数。
    (static)静态局部变量:数据区;生命周期是当前程序,作用域是当前语句块、函数。

    3.全局变量、静态全局变量


    全局变量:数据区;生命周期是当前程序,作用域是当前程序。
    注意不能被auto修饰,全局变量是静态内存分配。
    (static)静态全局变量:数据区;生命周期是当前程序,
    作用域是当前文件。不能跨越.c文件

    4.全局变量与外部变量


    全局变量可以被声明外部变量,所以外部变量是静态内存分配。
    静态全局变量因为作用域的限制,不能被声明为外部变量。

    汇总五 (运算符)

    1.浮点类型数据不能取余!


    2.前++、前--         

      运算规则:先运算,后自增\自减

    1. int a = 1, b = 2;
    2. a = b++;
    3. printf("a == %d, b == %d\n", a, b);
    4. // a == 2, b == 3

    3.后++、 后--
    运算规则:先自增\自减,后运算

    1. int a = 1, b = 2;
    2. a = ++b;
    3. // a == 3, b == 3

    4.逻辑运算

    1.逻辑运算的结果只有真假值,&&的优先级比||高,优先执行;

    2.|| 运算有提前截断现象,左条件式为真时,右条件不会执行。

    1. #include <stdio.h>
    2. int main(int argc, const char *argv[])
    3. {
    4. int a=1, b=2;
    5. if( a++ || b++ ){
    6. printf("a=%d, b=%d\n", a, b);
    7. }
    8. return 0;
    9. }
    10. //a=2,b=2

    5.位运算

    参与运算的量,按二进制位进行运算。
    包括位与(&)、位或(|)、位非(~)、位异或(^)、左移(<<)、右移(>>)六种。

    6.条件运算符(三目运算符)


    表达式A ? 表达式B : 表达式C
    这是一个三目运算符,用于条件求值,表达式A如果为真,执行表达式B,反之执行表达式C。

    汇总六 (输入输出)

    1.输出字符  putchar

    1. int putchar(int);
    2. eg:
    3. char a = 'A';
    4. putchar(a);
    5. 参数: 为字符常量、变量或表达式
    6. 功能:把字符c输出到显示器上
    7. 返值:正常,为显示的代码值;

    2.输出字符串 puts

    1. int puts(const char *);
    2. eg:
    3. char str[20] = "hello world";
    4. puts(str);
    5. 功能:向显示器输出字符串(输出完,换行)
    6. 说明:字符数组必须以‘\0’结束

    3.输入字符 getchar

    1. int getchar(void);
    2. eg:
    3. char c = getchar();
    4. 功能:从键盘读一字符
    5. 返值:正常,返回读取的代码值;出错或结束键盘输入,返回-1

    4.输入字符串

    1. char *gets(char *);
    2. eg:
    3. char str[20];
    4. gets(str);
    5. 功能:从键盘输入一以回车结束的字符串放入字符数组中,
    6. 并自动加‘\0
    7. 说明1:函数没有实现检查字符串长度能否完全放入,所以
    8. 输入串长度应小于字符数组维数。
    9. 说明2:与scanf函数不同,gets函数并不以空格作为字符
    10. 串输入结束的标志。
    1. #include
    2. int main(int argc, const char *argv[])
    3. {
    4. char string[15] = {0};
    5. printf("Input a string:");
    6. gets(string);
    7. printf("%s\n", string);
    8. return 0;
    9. }

    5.scanf

    1. int scanf(const char *restrict, ...);
    2. eg:
    3. int n;
    4. char str[20];
    5. scanf("%d %s", &n, str);
    6. %d 有符号整型 %c 字符 %s 字符串 %f 单精度浮点型
    7. %s 获取字符串时,提供的应当是一个指向字符数组的指针
    8. 功能:按指定格式从键盘读入数据,存入地址表指定存储单元中,并按回车键结束
    9. 返值:正常,返回输入数据个数
    10. 地址表:变量的地址,常用取地址运算符&

    在整型时

    字符型时

    吃掉摁下的回车键 ;   抑制符*的使用,吃掉了空格(字符之间多敲了一个空格)

    1. scanf2.c
    2. #include <stdio.h>
    3. 3.处理脏数据
    4. int main(int argc, const char *argv[])
    5. {
    6. char ch1, ch2, ch3;
    7. //%c 作为格式输入时,对空格键,tab键,\n 都作为一个有效字符读入
    8. scanf("%c%c%c", &ch1, &ch2, &ch3);
    9. printf("ch1 = %c ch2 = %c ch3 = %c\n",ch1, ch2, ch3);
    10. //enter 按键需要吃掉 getchar获取到这个\n
    11. getchar();
    12. //%*c抑制一个字符
    13. scanf("%c%*c%c", &ch1, &ch2);
    14. printf("ch1 = %c ch2 = %c\n", ch1,ch2);
    15. return 0;
    16. }

    6.3.处理脏数据
     

    1. //回收垃圾方式的三种方式
    2. //方法1:空格、若干空格、tab、\n
    3. #if 0
    4. scanf("%c %c %c", &a, &b, &c);
    5. #endif
    6. //方法2:%*c 回收任何一个字符, tab 键 ,空格键,\n
    7. #if 0
    8. //%*c 回收任何一个字符, tab 键 ,空格键,\n
    9. scanf("%c%*c%c", &a, &b);
    10. #endif
    11. //方法3:getchar()回收
    12. #if 0
    13. scanf("%c", &a);
    14. getchar(); //吃一个字符
    15. scanf("%c", &b);
    16. #endif
    17. printf("a=%c b=%c c=%c\n", a, b, c);
    18. return 0;
    19. }

    方式一可以吃掉多个空格

    若只是输入一个字符,建议方式三

    汇总七(控制语句)

    1.条件语句

        a.  if ----  else

    b.   Switch --  case  多条件选择语句

    2.循环语句

    a.while

    continue 当前循环到此结束,重新开始

    break则是退出循环

    b.   do ---- while

    1) while循环中 (条件)后面没有分号,do while 循环中 (条件) 后面有“,”

    2) while与do while执行循环体与判断的顺序不同
    3)各自的应用场合不同。while强调“条件是否满足”do while强调“动作的行为”

    两个死循环

    c.for循环

    3.break与continue

    break

    break从循环体内跳出,即提前结束当前循环
    注意:     

    break只能用在循环语句 和 switch语句中。

    continue


    continue语句结束本次循环,接着判定下一次是否执行循环。
    注意:
    continue只结束本次循环,而break终止本层循环
    continue是循环控制语句,不能实现跳出条件语句if、switch。

    4.return

    return语句的一般形式: return(<表达式>)主要用于终止包含它的函数的执行若终止的为主函数,则主程序结束
    return 表达式的结果可以被返回到调用函数接收存储。

    return的值一般有以下几种含义:
    1.函数是否正常执行的反馈
    库函数常用0表示正常结束,非0有异常情况

    自定义函数,判定真假,非零为真
    2.函数需要返回一个运算结果值
    根据定义的返回值类型,存储、返回值。传值要注意类型一致,或主动强制转换

    汇总八(数组)

    1.一维数组


    1.1.数组的定义


    <存储类型> <数据类型> <数组名> [N];
    1. 数据类型表示每个成员的数据类型;
    2. 数组名代表数组的首地址,是常量地址
    3. N是数组定义时申请的成员数量。
    4. 每个成员依次使用0,1,2,3......N-1来标记成员在数组中的位置,这个标记称作 下标;
    5. [ ] 是数组的取值符号,定义时里面填写申请的数组成员数量;调用时里面填写下标值,用来取          特定下标成员的值:数组名字[n],表示下标为n的数组成员的值;
    6. & 是取地址符号,用来获取变量的首地址,可以和数组结合,用来获取特定数组位置的首地址。
    7. 符号 * 是指针的取值符号,这里因为数组也和地址有关系,所以可以使用符号 * 来做取值操作。


    注意 :数组是顺序的使用一块连续的存储空间的构造类型

     a   &a 值相等,表示的含义不同

    a 一维数组a的常量地址,代表整个数组。
    &a 取整个数组的首地址


    a[1] 一维数组a的第二个成员的值。
    &a[1] 一维数组a的第二个成员的首地址。
    a+1 从一维数组a的第一个成员首地址,偏移一个成员单位,到第二个成员的首地址。
    *(a+1) 一维数组a的第二个成员的值。

    1.2数组的初始化

    1.data[5]   使用的下标为0 . 1 . 2 . 3 . 4 

    2.若初始化一部分则后面的值自动补0

    1. #include <stdio.h>
    2. int main(int argc, const char *argv[])
    3. {
    4. /**********定义**********/
    5. //定义一个有5个int成员的数组dataA
    6. int dataA[5];
    7. /**********定义并初始化**********/
    8. //定义一个有5个int成员的数组dataB, 并初始化一部分
    9. int dataB[10]={1,2,3,4,5};
    10. int dataC[] = {1,2,3,4,5};
    11. /**********观察数组成员初始值**********/
    12. //dataA[0] dataA[1] dataA[2] dataA[3] dataA[4] dataA[5] ......
    13. printf("sizeof(dataA)=%u,dataA[5]=%d\n",sizeof(dataA), dataA[5]);
    14. //error: dataA[5] 越界了
    15. printf("sizeof(dataB)=%u,dataB[5]=%d\n",sizeof(dataB), dataB[5]);
    16. printf("dataB[10]=%d\n", dataB[10]);
    17. //error: dataB[10] 越界了,dataC只有0~9个成员,编译器不检查数组越界!!!
    18. //sizeof计算数组申请的长度
    19. int n = sizeof(dataC)/sizeof(int);
    20. printf("dataC has %d members\n", n);
    21. printf("sizeof(dataC)=%u,dataC[5]=%d\n",sizeof(dataC), dataC[5]);
    22. //error: dataC[5] 越界了,dataC只有0~4个成员,编译器不检查数组越界!!!
    23. return 0;
    24. }

    1.3数组的赋值和初始化

    数组为构造类型,不能直接赋值和读取,二者都需要借助for循环

    1. #include <stdio.h>
    2. int main(int argc, const char *argv[])
    3. {
    4. /**********定义**********/
    5. //定义一个有5个int成员的数组dataA
    6. int dataA[5]={1,2,3,4,5};
    7. int i;
    8. /**********遍历(调用)**********/
    9. for(i=0; i<5; i++){
    10. printf("dataA[%d]=%d\n", i,dataA[i]);
    11. }
    12. /**********赋值**********/
    13. #if 0
    14. //error 数组不能整体赋值
    15. //dataA={5,4,3,2,1};
    16. //dataA[5]={5,4,3,2,1};
    17. #else
    18. //right
    19. for(i=0; i<5; i++)
    20. {
    21. dataA[i] = i+1;
    22. }
    23. #endif
    24. return 0;
    25. }

    注意事项

    1) 数组必须逐个元素引用,而不能整体引用。
    2) 数组名是常量,不能被赋值。

    数组定义后,其空间就确定下来了,所以为常量
    3) 同个数组中的所有元素的数据类型都是相同的。
    4) 不能在方括号中用变量来表示元素的个数,但是可以是符号常数或常量表达式。

    1.4 排序

    冒泡排序

    从标准输入获取数字

    1. #include<stdio.h>
    2. #define N 10
    3. int main(int argc, const char *argv[])
    4. {
    5. int data[N]={0};
    6. int a,i,j,temp;
    7. for(a=0;a<=N-1;a++){
    8. scanf("%d",&data[a]);
    9. }
    10. for(i=0;i<=N-1;i++)
    11. {
    12. for(j=0;j<=N-1-i;j++)
    13. {
    14. if(data[j]<data[j+1])
    15. {
    16. temp=data[j+1];
    17. data[j+1]=data[j];
    18. data[j]=temp;
    19. }
    20. }
    21. }
    22. for(i=0;i<N;i++)
    23. {
    24. printf("%d ",data[i]);
    25. }
    26. putchar(10);
    27. return 0;
    28. }
    1. sort_maopao.c
    2. #include <stdio.h>
    3. #define N 10
    4. int main(int argc, const char *argv[])
    5. {
    6. int a[N] = {2, 5, 1, 3, 4, 10, 7, 9, 8,
    7. 6};
    8. int i = 0, j = 0;
    9. int temp = 0;
    10. /* 冒泡的趟数 ,N 个数, N-1*/
    11. for (i = 0; i < N-1; i++){
    12. // 每排一趟序,找到一个最大值,下次比较元
    13. 素个数减1
    14. for (j = 0; j < N-1-i; j++){
    15. //较大的数值下沉
    16. if (a[j] > a[j+1]){
    17. temp = a[j];
    18. a[j] = a[j+1];
    19. a[j+1] = temp;
    20. }
    21. 缺点:数据读取、存储、交换次数太频繁。
    22. 简单选择排序:
    23. }
    24. }
    25. for ( i = 0; i < N; i++){
    26. printf("%d ", a[i]);
    27. }
    28. putchar(10);
    29. return 0;
    30. }

     2.字符数组

    2.1定义和初始化

    1. #include
    2. #define N 10
    3. int main(int argc, const char *argv[])
    4. {
    5. int i = 0;
    6. char ch;
    7. #if 1
    8. char str[N];
    9. #endif
    10. #if 0
    11. char str[N] = {'h','e','l','l','o'};
    12. #endif
    13. #if 0
    14. char str[N] = "hello";
    15. #endif
    16. #if 0
    17. char str[] = "hello";
    18. #endif
    19. #if 0
    20. while( ((ch=getchar()) != '\n') && (i
    21. {
    22. str[i++] = ch;
    23. }
    24. #endif
    25. #if 1
    26. for(i = 0; i < N; i++)
    27. {
    28. printf("%d:%c\t", str[i], str[i]);
    29. }
    30. putchar(10);
    31. #endif
    32. //scanf("%s", str);
    33. //printf("%s\n", str);
    34. return 0;
    35. }

    输入可采用 scanf

    输出可采用printf

    易出现问题及应对方法
    问题:字符数组未初始化的使用
    1) char a[10];
    for 赋值 {'h','e','l','l','o'}; 不能整体赋值构造类型!

    不能整体赋值,a属于常量地址,不能被赋值


    2) char a[10];
    赋值 "hello";
    如果数组没有初始化,局部变量空间存储内容情况是未知的。
    第一种情况的数组赋值后,'o'后面不一定哪个位置有\0;
    第二种情况的数组赋值后,'o'后面自动填充了'\0'。

    2.2 字符串函数

    2.2.1 求字符串长度
    1. 1. 函数原型:
    2. #include <string.h>//头文件
    3. size_t strlen(const char *s);
    4. 2.
    5. 参数:字符串首地址(地址==指针);
    6. 返回值:int , 获取的字符串长度,不包括‘\0’.
    7. #include <stdio.h>
    8. #include <string.h>
    9. #define N 20
    10. int main(int argc, const char *argv[])
    11. {
    12. char string[N] = "hello world";
    13. int len = strlen(string);
    14. //len =strlen("hello world");
    15. //printf("len = %d, string = %s\n",strlen("hello world"), string);
    16. printf("len = %d, string = %s\n", len,string);
    17. return 0;
    18. }

    2.2.2

    汇总九(二维数组)

    9.1 二维数组的定义和初始化

    <存储类型> <数据类型> <数组名> [行][列]
    例如:int b[3][5] = {{0,1,2,3,4},{5,6,7}};
    数组元素个数:M*N
    数组内存大小:M*N*数据类型大小
    注意:存储空间是连续的

    b  表示第0行的值

    b[0] 表示第0行的第一个数

    &b[0] 表示第0行第0列的数

    加[]降一级,&则升一级

    []表示取值,&表示取地址 ,可以抵消

    第一二行表达的意思一样

    第三四行表达的意思一样

    举例:

    b b+0 二维数组第一行的首地址,指针常量,数组行地址

    1. &b[0] +1 第二行首地址
    2. &b[1] +1 第三行首地址
    3. &b 二维数组的首地址
    4. b b+0 二维数组第一行的首地址,指针常量,数组行地址
    5. b+1 二维数组第二行的首地址
    6. b[1] b[1]+0 二维数组第二行的第一个元素的首地址
    7. b[1]+1 二维数组第二行第二个元素的首地址
    8. &b[1] 二维数组第二行的首地址
    9. b[1][1] 二维数组第二行第二个元素值
    10. &b[1][1] 二维数组第二行第二个元素的首地址
    11. &b[1]+1 二维数组第三行的首地址
    12. &b+1 二维数组的末尾的地址(此字节的空间已经不属于当前数组)

    易出现问题及应对方法
    问题1:二维数组初始化方法
    解决方法:
    1)降维给二维数组初始化。每一组的初值都用大括号{ }括
    起来;
    2)按线性存储形式给二维数组初始化。;
    3)可以省略左边下标范围的方式给二维数组初始化。
    问题2:使用数组需要注意的几点
    解决方法:
    1)数组是不能整体赋值的,只能定义时整体初始化。
    2)要防止下标越界使用数组。
    3)数组名是常量,不能修改也不能赋值。

    实践:从标准输入输入10个数,并且比较大小

    1. #include<stdio.h>
    2. int main(int argc, const char *argv[])
    3. {
    4. int i,j,max;
    5. int a[2][5]={0};
    6. for (i=0;i<2;i++)
    7. {
    8. for(j=0;j<5;j++)
    9. {
    10. scanf("%d",&a[i][j]);
    11. }
    12. }
    13. max = a[0][0];
    14. for(i=0;i<2;i++)
    15. {
    16. for (j=0;j<5;j++)
    17. {
    18. if(max < a[i][j])
    19. max = a[i][j];
    20. }
    21. }
    22. printf("max = %-8d",max);
    23. return 0;
    24. }

    9.2 二维数组与字符串

    1. #define N 10
    2. int main(int argc, const char *argv[])
    3. {
    4. #if 0
    5. char data[2][10];
    6. #endif
    7. #if 0
    8. char data[2][10] = {"hello", "world"};
    9. #endif
    10. #if 1
    11. char data[][N] =
    12. {"hello","world!","hello!"};
    13. #endif
    14. int n = sizeof(data)/N;
    15. printf("n = %d\n", n);
    16. int i;
    17. for(i = 0; i < n; i++){
    18. printf("%s\n", data+i); //行地址
    19. data[i]
    20. }
    21. return 0;
    22. }

    汇总十(指针)

    指针:一个变量的地址(内存单元的地址)
    指针变量:专门存放常量、变量的地址的变量叫指针变量

    10.1 一级指针

    一级指针一般形式如下:
    <存储类型> <数据类型> * <指针变量名> ;

    1.指针的存储类型是指针变量本身的存储类型。
    2.指针的数据类型是指针目标的数据类型。

    1. &a 普通变量的地址
    2. a_p 普通变量的地址
    3. a 变量的值
    4. *a_p 通过指针间接访问到变量的值
    5. &a_p 指针变量的地址
    6. 问题:什么是间接访问?
    7. 直接访问:a
    8. 间接访问:*a_p

    10.2 二级指针

    存储一级/指针变量的地址
    <存储类型> <数据类型> ** <指针名字>;

    10.3 野指针

    为了防止定义变量未给初值 或 释放空间后非法访问,产生野指针,初始化设置或重新赋值指针值为NULL,称空指针。

    空指针可以用来判断指针赋值、使用情况。
    在本课程提供的系统、编译器环境下,源码定义NULL是宏,是((void *)0)

    10.4 静态指针

    static 变量是内存管理静态分配的,所以生命周期是持续到程序结束。
    static 声明的全局变量、函数在当前程序中只初使化一次,只能在当前文件内被调用。
    static 声明的局部变量是函数内部变量,只需初始化一次,再次调用也是同一个变量,其只能在当前函数内被调用。

    10.5 常量指针

    const 修饰的变量是指常量化变量的值,这类变量的值只
    能初始化,不能被后续修改。
    一般说明形式如下:
    const <数据类型> 变量名 = [<表达式>] ;
    变量有 const 修饰时,若想用指针间接访问变量,指针也
    要有 const 修饰。

    1.常量化指针目标
    一般说明形式如下:
    const <数据类型> * <指针变量名称> = <指针运算表达式>;
    常量化指针目标是限制通过指针改变其目标的数值 ,但<指针变量>存储的地址值可以修改。

    const在指针类型的前面,说明const修饰的指针所指向的内存空间,不能通过指针去修改,但是可以对变量赋值,  eg:num = 33;指针的指向可以修改

    cont int *  与  int const int -*  表达的意思一样


    2.常量化指针变量
    一般说明形式如下:
    <数据类型> * const <指针变量名称> = <指针运算表达式>;
    使得<指针变量>存储的地址值不能修改。但可以通过 *<指针变量名称> 修改指针所指向变量的数值

    cosnt在最前面,表达的意思是 内存空间中值不能通过指针(即间接访问)来进行修改

    const在指针变量名的前面,说明const修饰的是指针变量,表示不能改变指针变量的指向,但是可以修改指向的内存空间的数据

    const 关键字的作用主要有以下几点:
    (1)可以定义 const 常量,具有不可变性。
    (2)便于进行类型检查,使编译器对处理内容有更多了
    解,消除了一些隐患。
    (3)可以避免意义模糊的数字出现,同样可以很方便地进
    行参数的调整和修改。
    (4)可以保护被修饰的东西,防止意外的修改,增强程序
    的健壮性。

    1. 实践1
    2. char* s="AAA";// const char *
    3. 保持类型一直,因为左面是变量,右面是常量
    4. printf("%s",s);
    5. s[0]='B';
    6. printf("%s",s);
    7. 参考答案:"AAA" 是字符串常量。s是指针,指向这个字符串常量,所以声明s的时候就有问题。应当类型一致,const char* s = "AAA";
    8. 然后又因为是 const * 限制了通过指针修改对象,所以对s[0] 的赋值操作是不合法的。
    1. 实践2
    2. 下列的各种定义中关键字 const 是什么含意?
    3. const int a;
    4. int const a;//这两行都是修饰的变量a,使a变为常量存到静态存储区
    5. const int * a;
    6. int const * a;//这两行表达的意思一样,指针的只可以被修改,即可以指向其他常量化的变量;但是指向的一定得是常量化的变量,即初始化不可以被修改
    7. int * const a;//指针是常量化的,指针指向一个变量后就可以再次修改了,
    8. int const * const a;
    9. 答案参考:
    10. 前两个的作用是一样,a是一个常整型数。
    11. 第三、四个的作用是一样,意味着a是一个指向常整型的指针(也就是,整型数是不可修改的,但指针可以)。第五个意思a是一个指向整型的常指针(也就是说,指针指向的整型是可以修改的,但指针是不可修改的)。
    12. 最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。

    好题1:

    1. int main(int argc, const char *argv[])
    2. {
    3. int m=0,n=3;
    4. if(m>0)
    5. if(n>2)
    6. printf("A");
    7. else
    8. printf("B");
    9. return 0;
    10. }
    11. 运行的结果是什么?
    12. 答案:没有任何输出。
    13. if 语句和 else 默认就近匹配, 当然 if 语句可以没
    14. else 匹配。加花括号可以调整语句所属的范围。因此
    15. 第一个 if 后面没有花括号限制语句块的范围,则后面的第
    16. 二个 if 算做第一个 if 里面的内容,跟着的 else 就近
    17. 原则和第二个 if 匹配,构成 if...else... 语句。第
    18. 一个 if 没有 else 匹配。所以反思得到,写语句块类的
    19. 代码时,为了避免格式歧义导致的逻辑错误,请不要省略花
    20. 括号。

     好题2:

    1. 2.以下程序执行后,i 的值是多少?
    2. int i = 0;
    3. do{
    4. i++;
    5. }while(i>0);
    6. i++;
    7. A.1
    8. B.2
    9. C.0
    10. D.以上无结果
    11. 答案:D。解析: do{...}while 语句会先执行循环体内
    12. 语句一次后,才会执行 while 判断语句。因此,进入 do
    13. 后,i 自增为 1, 1>0, 满足 while 判断条件,继续执
    14. 行循环、陷入循环,程序执行到数据溢出正整数极限,变成
    15. 负数,不满足判断条件结束循环后,数据是一个非常大的负
    16. 数。
    17. 因为符号位会被占据,变为负数

  • 相关阅读:
    项目实战:通过axios加载水果库存系统的首页数据
    SpringCloud微服务技术栈-什么是Docker?怎么安装Docker?
    【Node.JS 】服务器相关的概念
    docker registry 镜像同步
    蓝桥杯:买不到的数目
    第5集丨理学对佛、道的复制
    [附源码]计算机毕业设计JAVA博客系统设计
    团队协作:如何利用 Gitee 实现多人合作项目的版本控制
    腾讯薪酬改革:晋升不再直接调薪;iPhone 4S 和 6S 将被列入过时产品;Perl 5.36.0发布|极客头条
    [数据结构C++实现]二叉搜索树
  • 原文地址:https://blog.csdn.net/2302_76785838/article/details/133917415