C语言重点知识复习2

来源:互联网 发布:go高级编程书籍 编辑:程序博客网 时间:2024/06/06 04:55

1.指针的算术运算
(1)指针之间不允许相加,但允许相减
指针相减表示两个指针之间间隔的单元格数(1.先计算出字节数 2.再除以权重)
(2)指针运算需要调整
p+数字(n) 加n单元格的权重 权重为指针变量去掉一个*,求sizeof(),乘n
数字之间不需要调整,直接加或减

#include <stdio.h>#include <stdlib.h>int main(){    int arr[10] = {1,2,3,4,5,6,7,8,9};    int *p = arr; //指针-指针    int *q = &arr[8];    printf("%d\n",p-q);//-8    printf("%d\n",q-p);//8    printf("%d\n",(short *)q-(short *)p);//16    printf("%d\n",(double *)q-(double *)p);//4    printf("%d\n",(unsigned long)q-(unsigned long)p);//32    int *p1 = (int *)2000;//指针+-数字    printf("%d\n",p1+2);//2008    printf("%d\n",(char *)p1+2);//2002    printf("%d\n",(long long)p1+2);//2002    printf("%d\n",(double **p1+2);//2008}

2.数组和指针的替换

int arr[10];int *p = arr;arr[i] = *(arr+i);p[i] = *(p+i);

3.指针和数组的其他知识
(1)数组名代表整个数组长度的两种情况

int arr[10] = {0,1,2,3,4,5,6,7,8,9};sizeof(arr) = 40;cout<<&arr<<endl;//1000cout<<&arr+1<<endl;//1040

(2)类型

int arr[10];   int *p = arr;int brr[3][4]; int (*q)[4] = brr;//二维数组的数组名是指向一位数组的指针

brr[0]是int*类型
brr[0]+1是int*类型(+数字,对类型无影响)
brr[2][3]是int类型

(3)二位数组是否越界

int brr[3][4] = {{1,2,3},{4,5,6},{7}};  printf("%d\n",brr[0][6]);//6  二维数组是线性存储的,可以越界访问

(4)字符串的定义正确的是?

char str1[5] = {'a','b','c'};//ok      char str2[5] = {"abc"};//ok         char str3[5] = "abc";//ok  char str4[] = "hello"; //ok         char str5[5] = "hello";//error,越界

(5)字符数组的大小
sizeof—求内存的字节数,所有的字符都要放进去
strlen—字符串的有效长度,碰到’\0’就结束

#include <stdio.h>int main(){    char str1[100] = "abcde";    char str2[100] = "abcd\0ef\n";    char *str3 = "abcde";    char *str4 = "abcd\0ef\n";    char str5[] = "abcde";    char str6[] = "abcd\0ef\n";    printf("%d,%d\n",sizeof(str1),strlen(str1));//100,5    printf("%d,%d\n",sizeof(str2),strlen(str2));//100,4    printf("%d,%d\n",sizeof(str3),strlen(str3));//4,5    printf("%d,%d\n",sizeof(str4),strlen(str4));//4,4    printf("%d,%d\n",sizeof(str5),strlen(str5));//6,5    printf("%d,%d\n",sizeof(str6,strlen(str6);//9,4    return 0;}

(6)字符数组和字符串常量的区别

int main(){    char *str1 = "abcde";//1       char str2[] = "abcde";//2       str1[0] = 'x';//3 编译没问题,运行崩溃    str2[0] = 'x';//4    return 0;}

str1是字符常量,在全局静态变量区(.rodata段),不能修改其值
str2是字符数组,在栈上,自己的内存,可以随便修改
改错题可能会考,需要在定义时显示的加上const,这样编译就不会通过
const const char *str1 = “abcde”;

(7)下列各变量的含义

int *a;//整型指针int *b();//函数,无参数,返回值是int *int c[4];//整型数组int *d[4];//指针数组,每个数组的元素是一个int类型的指针int (*e)[4];//数组指针,该指针指向一个含有4个整型元素的数组int (*f)();//函数指针,该指针指向一个函数,函数无参数,返回值是int类型

4.交换函数

#include <stdio.h>void Swap1(int *p1, int *p2){    int *tmp = p1;    p1 = p2;    p2 = tmp;}void Swap2(int *p1, int *p2){    int *tmp;//野指针    *tmp = *p1;    *p1 = *p2;    *p2 = *tmp;} void Swap3(int *p1, int *p2){    int tmp = *p1;    *p1 = *p2;    *p2 = tmp;}int main(){    int a = 10;    int b = 20;    printf("a=%d,b=%d\n",a,b);    Swap1(&a, &b);    printf("swap1:a=%d,b=%d\n",a,b);    Swap2(&a, &b);    printf("swap2:a=%d,b=%d\n",a,b);    Swap3(&a, &b);    printf("swap3:a=%d,b=%d\n",a,b);    return 0;}

这里写图片描述

这里写图片描述

这里写图片描述
子函数和父函数之间要建立联系,必须传指针并解引用

5.返回数组/指针

#include <stdio.h>char *Fun1(){    char arr[] = "hello world";    return arr;}int main(){    printf("%s\n",Fun1());///返回局部数组,乱码}`

这里写图片描述
arr是局部变量,出Fun1函数后,函数栈帧回退,arr的地址可能已经被重新分配给别的函数使用。不能返回局部变量!!!

6.结构体和联合体

struct A{    char a;//1+1    short b;//2    int c;//4};//8struct B{    char a;//1+3    int b;//4    short c;//2};//10+2struct C//位段{int a:10;//a占10位int b:2;//a占2位};//4,必须是int的倍数struct D{    char a;//1    struct DD//有类型有变量,以单个最大的数据类型对齐    {        char b;//1+3        int c;//4    }d;//8};//9+3struct E{       short a;//2       struct EE//有类型没变量,不占内存       {           char b;           int c;       };//不占内存       int d;//4};//6+2struct F{    int a;//4    struct//没类型没变量,生成一个透明的变量,a/b/c/d同级     {        char b;//1+3        float c;//4    };    char d;//1+3};//16struct G{       char a;//1       struct//只有变量没有类型(与有变量有类型)相同       {           char b;//1+3           int c;//4       }d;//8};//9+3union H//共用体{    char a;    short b;    int c;};//4 

7.可变参数编程 3个宏

需要引入头文件#include<stdarg.h>va_list  list;//相当于char* list;va_start(list, num);//找到...开头va_arg(list,int);//从…取数据va_end(list);//list==NULL,关闭

编程题:编写一个名叫max_list的函数,它用于检查任意数目的整型参数并返回它们中的做大值,参数列表必须以一个负数结尾,提示列表的结束

#include <iostream>#include <stdarg.h>using namespace std;int Max_list(int a,...)//1,4,9,-1{    int max = a;    int cur = a;    va_list list;//char *list;    va_start(list,a);//找到...开头    while(cur >= 0)    {        cur = va_arg(list,int);//从...取数据        if(max < cur)        {            max = cur;        }    }    va_end(list);//list = NULL;    return max;}int main(){    printf("%d\n",Max_list(1,5,9,0,2,5,-1));    return 0;}

8.malloc常见错误
这里写图片描述
malloc一般都是内存的问题(程序崩溃/内存泄露)

面试题:C++是兼容C的,C已经有了malloc/free,C++为什么还要有new/delete?
答:malloc/free是C语言的标准库函数,new/delete是C++的运算符
对于非内置数据类型的对象来说,使用malloc/free无法满足动态创建对象的要求。对象创建的时候要自动调用构造函数,对象消亡的时候要自动调用析构函数。malloc/free是库函数,不在编译器权限的控制范围内,不能把调用构造函数和析构函数的任务强加给malloc/free。因此,C++需要一个能完成动态分配并初始化内存的运算符new,一个可以清理并释放内存的运算符delete。

原创粉丝点击