数组和指针,c复习计算

int a[10]中的a是数组名,它指向数组中的第一个因素。不过当其做为sizeof的操作数,也许利用&取地址的时候,要把a用作带个数组来设想。

本节过逝。==================================================================

1.指针

#include <stdio.h>
void test_fuc(int b[][3])
{
    ++b;
    b[1][1]=820;
}
int main(void)
{
    int a[][3]={
        {1,2,3},
        {4,5,6},
        {7,8,9}
    };
   test_fuc(a);
   printf("a[2][1]=%d\n",a[2][1]);
    return 0;
}

先看一个例子:

数组类型:是一个复杂类型;(由数组成分类型和数老董度综合表述)如下;数组类型是:(int
[]);

1.1 指针的概念

指南针变量的值是地点

int main(int argc, char *argv[]) { 
    int a = 100;
    int b = 200;
    int *p = &a;
    printf("\n a = %d,*p = %d",a,*p);
    printf("\n &a = %x,p = %x",&a,p);
    p = &b;
    printf("\n b = %d,*p = %d",b,*p);
    printf("\n &b = %x,p = %x",&b,p); 
    return 0;
}

输出:

int a[10] = {0};printf("%p, %p\n", a, &a);

项目标本色是:固定大小内部存储器块的小名。是模具。
一. 对一维数组 C语言规定: int c[10];

1.2 改造多少个变量,要求以此变量的地址

假使变量是数额,则须求指针
即使变量是指针,则要求二级指针保存指针变量的地址

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

void change(int a){
    //创建一个新建的变量 
    a = 8;
}

void changeA(int *p){
    //创建一个指针接受&a ,地址 
    *p  = 8;//*(地址)赋值 
}


int main(int argc, char *argv[]) {

    int a  = 10;
    change(a);
    printf("a = %d",a);
    changeA(&a);
    printf("\na = %d",a);
    return 0;
}

www.5929.com 1

打印结果是0xbfc077b4, 0xbfc077b4。两个的值是完全一样的,然则它们的品类分化。a意味着的是数组第二个成分的位置,类型是int*&a代表数组a的地址,类型是int [10],贰个针对包括十个int成分数组的指针。

1.一维数组名:c是数组首成分的地址,c+1步长为 4个字节,多少个 int
成分大小。
&c是整整数组的地方,&c+1小幅度为叁二十一个字节,11个 int 成分大小
即便如此c和&c的值同样,可是她们所表示的宽度不一样。
2.数组第i 个因素那样表示:c[i] 或 *(c+i); 给它赋值。c[i] = 5 或
*(c+i) = 5;

1.3 数组名是指针

int main(int argc, char *argv[]) {

    int a[7] = {1,2,3,4,5,6,7};
    int i =0;
    for(;i<7;i++){
        printf("\n %d , %x",a[i],&a[i]);
        printf("\n %d , %x",*(a+i),a+i);
    } 
    //a是指针  a+i表示以a的数据类型的指针为步长,向后走i个单位的地址
    //*(a+i)取出那个地址里的数据 
    return 0;
}

数组充当函数参数的时候,会退化成指针,然而只退化二回,int
b[][3]作为参数会形成(*b)[3];b是三个指针,指向三个数组,数组含有3个int类型的因素。++b之后,注意大家b的门类,一旦移动叁个大幅,相当于活动3个int地点,所以++b之后,b指向的是a[1][0];然后b[1][1];相当于b又移动了1个上升的幅度,即移动3个int位也正是对应a[2]了,在b[1]的根基上,再使用[1],约等于对应a[2][1];所以最终打字与印刷a[2][1]等价于b[1][1].

大家能够使用下例对上述结论进行表明:

本节终结。==================================================================

1.4 指针类型的意思

指南针的精神是三个伊始地址,指针类型明确了从开场面址初阶截取多少长度。

平常大家习贯使用[]如此那般的下标运算代替指针运算,不过大家要领悟贰个道理,b[1][1]等价于*(*(b+1)+1).

int b[10] = {0};printf("%p, %p, %p, %p\n", b, &b, b+1, &b+1); 

二. 多维数组(int a[3][4])
1.多维数组名:a是指向三个一维数组 的数组指针,a
的增长幅度为一维的长短(即每便+1都跳一行)(17个字节,七个int成分成分大小)
2.(a+i)代表是全体第i行的地址,(代表二级指针)
*(a+i)代表第i行首元素地址 (代表拔尖指针)
*(a+i)+j或(&a[i][j])代表第i行第j个要素的地址
*(*(a+i)+j)或(a[i][j])代表第i行第j个因素的值。

1.5空类型的指针还可以其余类型的地址,可是取不出去数据,因为不知情步长是不怎么,不可能截取

int main(int argc, char *argv[]) {

    int a = 10;
    void *p = &a;
    printf("\n &a = %x,p = %x",&a,p);
    //printf("\n *p = %d",*p); 报错
    return 0;
}

打字与印刷结果为0xbf890214, 0xbf890214, 0xbf890218, 0xbf89023ca+1的拉长率是贰个数组元素的轻重缓急,而&a+1的宽度却是整个数组的尺寸。

本节了却。==================================================================

1.6 指针也是一种数据类型

数组当函数参数的时候,其项目退化为指针。来看一下例证:

三.多维数组做函数参数的滑坡难点
“数组做函数参数时会退化为指针” 如下代码:sizeof(a) == 4; sizeof(b) ==
4;都以七个指针大小,并不是数组大小。
“只不过各样退化后的数组(为指针)步长大概两样”。
全体的数额在内存里面都是线性存款和储蓄的。包含多维数组
1.一维数组的实参传递(实参把值传给形参):
int fun(char a[20],int n);(fun是被调函数)
int fun2(char b[3][数组和指针,c复习计算。4]);
sizeof(a)的是4个字节;
sizeof(a)/sizeof(*a)的是4(因为*a是char型成分,多个字节);
1)高效
2)C语言管理a[n]的时候(形参),它从未章程知道n是几,它只略知一二&a[n](即a的地点)是不怎么,它的值作为参数字传送递进去了.

1.6.1 指针是变量,据有内存空间,用来保存内部存款和储蓄器地址

int test_func{ printf("the value is %d\n", sizeof; return 0;}int main(int argc, char* argv[]){ int arr[10] = {0}; test_func; return 0;}
  1. 等价关系:
    数组参数                等效的指针参数
    1)一维数组 char a[30]           指针 char *
    2) 指针数组 char *a[30]            指针的指针 char **a
    3) 二维数组 char a[10][30]         数组的指针 char
    (*a)[30];

1.6.2 *p正是通过保留在p的内部存款和储蓄器地址找到一块内部存款和储蓄器然后操作这些内部存款和储蓄器

在指针表明时,*p表示指针变量,

*p = 30;//*p放在=右侧,修改内部存款和储蓄器空间的值
c = *p;//*p放在=侧边,获取内部存款和储蓄器空间的值

上述例子中的sizeof为4,因为数组当函数参数时,退化成指针,所以sizeof其实是sizeof

 

1.6.3 指针变量和它指向的内部存款和储蓄器空间的变量是多个例外的概念

给p赋值只会变动指针变量的值,不会转移所指的从头到尾的经过
给*p赋值只会转移所指向的原委,不会转移指针变量的值

  • C语言汇总

本节甘休。===================================================================

1.6.4指针的数据类型是它所针对的内部存款和储蓄器空间的数据类型,指针的数据类型具有依附性子。

结论:指针的上升的幅度是根据它所指向的内部存款和储蓄器空间的数据类型来决定的。

四.指针的杂点:
1.”指针的本质:指向内部存款和储蓄器的地方”,
“未有内部存款和储蓄器就不曾内部存款和储蓄器地址,没有内部存款和储蓄器地址就不曾指针”。
2.”直接赋值是指针存在的最大要思”。
3

1.6.5对于参数是指针类型的了然:站在c编写翻译器的角度看,对于形参,假如是指针类型,c编译器只会分配八个字节内存

1.数据类型的原形:占一定内存大小的外号。
类型正是模具,变量是模具发生的家伙
2.变量的庐山真面目:(一段连接)内部存款和储蓄器空间的小名(是三个门牌号)
3.数组的开始和结果:如 arr[5]; arr数组空间的首成分的地点,
&arr代表的是整整数组的首地址,
arr+1;数组第一个成分的地方,向下活动多少个字节。
&arr+1;代表向下活动二十个字节,也便是三个数组内部存款和储蓄器空间大小。
&arr和arr的值一样,但 +1 的结果分歧,因为她俩俩实质上是数据类型差异
4.指针指向什么人,就把什么人的地点赋给指针
5.指针变量和它所指向的内存空间变量是三个不等的定义(”不懂”)
6.瞩目: return不是把内部存款和储蓄器块
六十多个字节给return出来,而是把内部存款和储蓄器块的首地址(内部存储器块标号0X23124)给return出来。
(如下代码:17行和27行输出的值一样)
#include <stdio.h>
#include <string.h>

1.7 直接赋值创设的四个典型化

标准一:定义二个变量(实参)和多少个变量(形参);
规格二:建设构造关系,实参取地址传给形参;
条件三:*p形参去间接的修改实参的值。

数组和指针,c复习计算。char *func1()
{
char arr[10];
strcpy(arr,”sdqwyg”);
printf(“arr:%s\n”,arr);
printf(“&arr:%p\n”,arr);
return arr;
}
int main(void)
{
char *ch = NULL;
printf(“&ch:%p\n”,ch);

1.8二级指针的二种内部存款和储蓄器模型

ch = func1();
printf(“ch:%s\n”,ch);
printf(“&ch:%p\n”,ch);
return 0;
}

1.8.1

void printArray(char **strArr,int num){
    int i = 0;
    for(;i<num;i++){
        printf("%8s",strArr[i]);
    }
} 

void sortArray(char **strArr,int num){
    int i = 0, j = 0;
    char *temp = NULL;
    for(i=0;i<num;i++){
        for(j=i+1;j<num;j++){
            if(strcmp(strArr[i],strArr[j])<0){
                temp = strArr[i];
                strArr[i] = strArr[j];
                strArr[j] = temp;
            }
        }
    }
}


int main(int argc, char *argv[]) {
    int i=0,j=0;
    char *temp = NULL;
    char *ArrayStr[] ={"bbbb","aaaa","dddd","cccc"};
    printArray(ArrayStr,4);
    sortArray(ArrayStr,4);
    printf("\n");
    printArray(ArrayStr,4);
    return 0;
}

C提升教学第一天===============================
1.构造体字节对齐原因:用空间换时间。
2.操作系统最入眼的职能:能源分配。
3.句柄:结构体变量
4.野指南针的特点:操作野指针自个儿变量未有别的难题;可是不能操作野指针指向的内部存款和储蓄器空间
就可以以给指针变量(int *p) p 赋任什么地方点。如(p = NULL; p = 0xaabb; p =
0x9988;)
但是无法操作野指针指向的内部存款和储蓄器空间(大多数情况都以那样)。(*p = 100;*p =
“sdb”;这种景观不得以)。
5.冒泡:for(int i = 0; i < n-1; i++)
for(j = 0;j < n-1-i; j++)
if(a[j] <a[j+1])
6.选择:for(int i = 0; i <n-1; i++ )
for(j = i+ 1; j< n; j++)
if(a[i] <a[j])
7.实参数组名,便是数组,sizeof(数组名)正是数组总大小
形参数组名,正是指针。sizeof(数组名)正是指针大小(种种操作平台湾大学小有分别)。

1.8.2

void printArray(char strArr[4][10],int num){
    int i = 0;
    for(;i<num;i++){
        printf("%8s",strArr[i]);
    }
} 

void sortArray(char strArr[4][10],int num){
    int i = 0, j = 0;
    char temp[10];
    for(i=0;i<num;i++){
        for(j=i+1;j<num;j++){
            if(strcmp(strArr[i],strArr[j])<0){
                strcpy(temp,strArr[i]);
                strcpy( strArr[i],strArr[j]);
                strcpy(strArr[j],temp); 
            }
        }
    }
}


int main(int argc, char *argv[]) {
    int i=0,j=0;
    char *temp = NULL;
    char ArrayStr[4][10] ={"bbbb","aaaa","dddd","cccc"};
    printArray(ArrayStr,4);
    sortArray(ArrayStr,4);
    printf("\n");
    printArray(ArrayStr,4);
    return 0;
}

 

1.8.3

对指针做函数参数的敞亮:
首先个角度:站在c编译器的角度来看,对形参假使是指针类型,c编写翻译器只会把它作为一个指针变量来看,(分配多少个内部存款和储蓄器)
第一个角度:大家只有在选拔指针所指向的内部存款和储蓄器空间的时候,大家才去关爱内存是一维的依然二维的。

void printArray(char **strArr,int num){
    int i = 0;
    for(;i<num;i++){
        printf("%8s",strArr[i]);
    }
} 

void sortArray(char **strArr,int num){
    int i = 0, j = 0;
    char *temp = NULL;
    for(i=0;i<num;i++){
        for(j=i+1;j<num;j++){
            if(strcmp(strArr[i],strArr[j])<0){
                temp=strArr[i];
                strArr[i]=strArr[j];
                strArr[j]=temp; 
            }
        }
    }
}


int main(int argc, char *argv[]) {
    int i=0,j=0;
    char buf[100];
    char **myarr = (char **)malloc(10*sizeof(char*));
    if(myarr==NULL){
        return;
    }
    for(;i<10;i++){
        myarr[i] = (char*)malloc(100*sizeof(char));
        if(myarr[i]==NULL){
            return;
        }
    }

    printArray(myarr,10);
    sortArray(myarr,10);
    printArray(myarr,10);
    for(i=0;i<10;i++){
        free(myarr[i]);
    }
    if(myarr!=NULL){
        free(myarr);
    } 
    return 0;
}

C进步第二天=======================================
1.由此指针 操作指针指向的内部存款和储蓄器,多少个要素
1)”首地址”;2)”步长(由指针指向的半空中决定)”
“指针最要害的意思在于直接赋值”
2.一旦是值传递,(即变量本身传递),形参的别样改变不会听得多了自然能详细讲出来到实参(”数组名除却,因为数组名是数组的首地址”)
www.5929.com,形参(被调函数里面包车型客车变量);实参(主调函数里面的变量)
3.只假使址传递,(即变量地址传递),形参的别的修改会影响到实参
1)地址传递, 2)传参进度中确立形参和实参的指针指向关系
3)被调函数内部通过*直接赋值
4.指针做函数参数:有输入和输出天性
1)输入天性:实参的内部存款和储蓄器已规定,在主调函数分配内部存储器
2)输出天性:在被调函数分配空间
5.字符数组初步化:(两种处境)
1)char str1[] = {‘a’,’b’,’c’,’d’};
printf(“str1: %s\n”,str1);
//打字与印刷出abcd+乱码,因为数组中绝非截至符’\0′;
2)char str2[100] = {‘a’,’b’,’c’,’d’};
printf(“str2: %s\n”,str2);
//打字与印刷出abcd;因为这一定于数组部分起首化,有截止符’\0′

1.9 数组指针

6.通过[]和通过*成效是等价的,都以操作指针所指想的内部存款和储蓄器,
int a = 10; int *p = &a; printf(“%d, %d\n”,*p,
p[0]);打字与印刷效果是平等的

1.9.1数组名是常量,数组首成分的地址和数组地址是三个不等的定义,数组名代表数组首成分的地点,是个常量。

//编译时期数组就会分配一片内存区域,为了能顺利回收内存
//为了能顺利回收内存,为了让编译器能拿回原始的首地址,编译器将a做成常量
//如果我们要修改数组,可以通过int *p=a的方式来创建一个指针变量进行修改 
int main(int argc, char *argv[]) {
    int a[3]  = {0};
    a = 0x12345;//表达式必须是可修改的左值 
    return 0;
}

C提升第三日======================================================

1.9.2 &a 和 a

&a是一体数组的地方,a是首成分的地址
&a是数组类型(步长是漫天数组的轻重缓急),a是数组首成分类型(步长是单个元素类型的大大小小)

int main(int argc, char *argv[]) {

    typedef int(myarr)[5];
    myarr arr = {1,2,3,4,5};//相当于int[5] arr={1,2,3,4,5}; 
    printf("%d",sizeof(arr));//20
    printf("\n%d",sizeof(&arr));//4 
    printf("\n%10d,%10d",arr,arr+1);//arr是元素的类型,步长是4 
    printf("\n%10d,%10d",&arr,&arr+1);//&arr是数组类型,步长是4*5 
    return 0;
}
  1. 平日数组(char p[4]);是三个数组,成分是字符。
    指针数组(char *p[4]);是三个数组,成分是指针。
    他俩俩的传参:1)”传递”:普通数组:func(p,len) “接收” void func(char
    *p,int len );或者 void func(char p[],int len ); 或者 void func(char
    p[4],int len );
    2)”传递” 指针数组: func(p,len) “接收” void func(char **p,int len);或者
    void func(char *p[],int len); 或者 void func(char *p[4],int
    len);
    当不鲜明形参类型时,假设是”值传递”:能够把实参的原型放上去,再实行优化或不优化都对。如”指针数组”
    若果是”址传递”;需求在实参原型上在拉长一个 “*”
    号,再扩充优化活不优化都对。
    2.指针与数组假使做平常变量;两个有本质有分别。
    指南针与数组假设做形参时,两个是等价的。

1.9.3数组指针

int main(int argc, char *argv[]) {
    int i =0;
    typedef int(myarr)[5];
    myarr arr = {1,2,3,4,5};//相当于int[5] arr={1,2,3,4,5}; 
    myarr *p = &arr;
    for(i;i<5;i++){
        printf("\n%3d",arr[i]);
        printf("\n%3d",(*p)[i]);
    }
    return 0;
}

3.sprintf的用法: char buf[100];格式化壹个字符串,中间带数字0:

1.9.4数组指针的二种概念格局

int main(int argc, char *argv[]) {
    int i =0; 
    int b[5] = {1,2,3,4,5};  
    int(*p)[5] = NULL;
    p = &b;
    for(;i<5;i++){
        printf("%4d",(*p)[i]);
    }
    return 0;
}

int main(int argc, char *argv[]) {
    int i =0; 
    int b[5] = {1,2,3,4,5};  
    typedef int(*parr)[5];
    parr p = NULL;
    p = &b; 
    for(;i<5;i++){
        printf("%4d",(*p)[i]);
    }
    return 0;
}

1)字符串自带甘休符(不是透过格式化给的);
sprintf(buf,”sadd\0dada\0sads\0″);然后打字与印刷内容:printf(“%s\n”,buf);内容为”sadd”;
2)格式化三个字符串,中间带数字0,以%d匹配;因为占八个字节,截止符(’\0’或’0’)占几个字节;
sprintf(buf,”sadd%ddada%dsads%d”,0,0,0);printf(“%s\n”,buf);
内容为”sadd0dada0sads0″
3)格式化一个字符串,中间带数字0,以%c相配;sprintf(buf,”sadd%cada%csads%c”,0,0,0);
printf(“%s\n”,buf);
printf(“%s\n”,buf);
int len =
sprintf(buf,”sadd%cada%csads%c”,0,0,0);它的重临值很入眼:是整个字符串的尺寸;

1.9.5二维数组的数组名

二维数组的数组名是首元素的地点
二维数组的数组名是三个指南针常量
二维数组的数组名是二个数组指针

//myarray是数组首元素的地址 
//myarray是一个指针常量 
//myarray是一个数组指针 
int main(int argc, char *argv[]) {
    int i=0;
    int j=0;

    int a[5]={4,2,7,3,9};
    int myarray[3][5];
    int (*p)[5] = &a;

    for(;i<5;i++){
        printf("%3d",(*p)[i]);
    }

    for(;i<3;i++){
        for(;j<5;j++){
            myarray[i][j]=i+j;
        }
    }

    printf("\n%10d,%10d",myarray,myarray+1);//步长是20 
    printf("\n%10d,%10d",&a,&a+1);//步长是20 
    p  = myarray;//p和myarray都是数组指针  
    return 0;
}

C进步第15日=================================
1.异或(一样为0,差异为1)的特征:1)自身和融洽异或为0;2)贰个数每一个人和0异或:维持不改变
3)一个数每一人和1异或:取反

1.9.6 对于 myarr[i][j] = *(*(myarr+i)+j)的推演

myarray[i][j] =
12;//给myarray[i][j]赋值,给myarray第i行第j列赋值,

myarray是多个数组指针,他的幅度是j

(myarray+i)表示二维数组第i行的数组的地方,

*(myarray+i)表示第i行的首成分的地点

*(myarray+i) + j表示第i行第j列,

*p放在等号左侧是赋值

* (*(myarray+i) + j) = 12;

备注: p[i] — > *(p+i)

2.左移<<:(左边废弃,左侧补0)。左移n位(”无越界意况下”),也就是原数乘以2的n的次方
右移>>:(右侧屏弃,侧边补0)。
3.掩码:通过连日的0和1结缘,0X0000110,
如(0X00ff00),通过掩码能够把有个别部位的值改动。

1.9.7

第i行第j列成分的地点: a[i]+j *(a+i)+j &a[i][j]
第i行第j列成分的值: *(a[i]+j) *(*(a+i)+j) a[i][j]

4.一维数组名:int a[10]; printf(“a:%d,a+1:%d\n”,a,a+1);
printf(“&a:%d,&a+1:%d\n”,&a,&a+1); 二种打字与印刷情状各异
尽管a和&a的值相同,但她们的数组类型是分裂等。
a:代表首成分地址,第0个因素地址,&a[0],第0个因素是int,
+1,就是+4个字节。
&a:代表任何一维数组的地方,整个数组的尺寸;

1.9.8区分数组指针与指针数组

       char *a[30] 
       char(*a)[30] 
      // () [] 具有同样的优先级,而且结合方向都是从左向右 
      (*a)是一个指针-----》
 char(*a)[30]就是数组指针,[30]用来表示步长(这个指针指向一个步长是30的数组)。
       char *a[30]    -----》 char*表示类型,  char *a[30]是指针数组。

数组类型

2.动态内部存款和储蓄器

5.”指针数组”:是叁个数组,每一种成分都以指针。 int *p[10];
“数组指针”:是几个指南针,指向数组的指针。 int (*p)[10];
有”typedef”是类型,没有”typedef”是变量
概念数组指针的三种方法:
1)先定义数组类型,再依靠数组类型定义指针变量(不时用)
int a[10] ;typedef int ARR[10]; ARR *p1 = &a;
p1, &a首行地址;首行地址转首成分地址:*p1;
第i个要素的地方*p1 +i; 取第i个要素的剧情:*(*p1+i);
2)直接定义数组指针变量(常用)
int a[10]; int (*p)[10]; p = &a;
3)定义数组指针类型,再依据类型定义变量(常用)
int a[10]; typedef int (*ARR)[10]; ARR p; p = &a;
6.多维数组
int a[3][4];
1)多维数组名”a”,代表第0个要素的地址(约等于全部多维数组首成分地址或首行元素地址)
“a+1″跳七个要素(int[4]),16个字节。
2)多维数组名取址”&a”,代表全体数组的地点。
“&a+1″跳整个数组大小(int [3][4]),48个字节 。
sizeof(a) == 48; sizeof(a[0]) == 16; sizeof(a[0][0]) = 4;
3)多维数组名就一定于数组指针;如上;( int (*p)[4] = a 或 int
(*q)[4] = NULL, q = a);
4)特殊情状,当(数组指针)与(多维数组的数组名的上涨的幅度)不一致时;
“”

2.1报名动态内部存款和储蓄器

malloc能报名出一块内部存款和储蓄器区域,再次回到此内部存款和储蓄器区域的首地址
要是将该首地址赋值给二个int*p,即int类型的指针变量,就规定了那块内部存款和储蓄器的单位步长是int的,就足以依附int来拓宽赋值和取值操作

#include <stdio.h>
#include <stdlib.h>  
int main(int argc, char *argv[]) { 
    int *p = (int *)malloc(20*sizeof(int));
    printf("\n%x",p);
    int i = 0;
    for(;i<20;i++){
        p[i] = i;
           *(p+i) = i;
        printf("\n%d,%d",p[i],*(p+i));
    } 
    free(p);
    return 0;
}

5)”二级指针与二维数组不是同一种等级次序”;

2.2 内部存款和储蓄器不能够一再释放

C进步第四天=================================================================

2.3

在编写翻译时期,char *p =
malloc(100);只会为p分配多个字节,独有当这段代码试行的时候,才会分配malloc的玖十五个字节,要是条件不树立以来,不会分配那玖十几个字节。不过char
p[100];那句代码,在编写翻译器就分配了九十多少个字节。

“定义结构体变量时,要把定义语句写在函数的定义区,即使写在别的地方,由于编写翻译器的主题材料,会变成定义变量不成事,编写翻译器不认知”。

3.字符串

“结构体变量之间能够扩充直接赋值,可是须要注意深拷贝和浅拷贝难题”(上面有讲明)
1.结构体:
Stu *s1 = NULL;
Stu p = { 20, “nihao”,”sada” };
s1 = &p; //这里的注意写法,给结构体指针变量全体赋值。(无法写成 *s1 = p
,原因
*s1是一度开首取结构体的剧情,因为s1未有赋值,也就是野指针,无法取值);
2.结构体的名是三个家常的变量(和 int a 中的 a 无异);

3.1 自动补’\0′

#include <stdio.h>
#include <stdlib.h>  
int main(int argc, char *argv[]) {

    char str[10] ="calc";
    printf("\n %d",sizeof(str));//10
    printf("\n %d",sizeof("calc"));//5

    char *st = "notepad";
    printf("\n %d",sizeof(st));//4
    printf("\n %d",sizeof("notepad"));//8 

    return 0;
}

3.结构体中给指针的赋值操作和数组的赋值操作。(极其注意)
ypedef struct Stu
{
int age;
char name[20];
char *p;
char *size;
}Stu;

3.2 字符数组开首化字符串,要是数CEO度小于字符串长度会报错,大于则自动补’\0′

#include <stdio.h>
#include <stdlib.h>  
int main(int argc, char *argv[]) { 
    //char str[3] = "calc";报错  
     char str[4] = "calc";//没有'\0' 
     int i =0;
     for(;i<4;i++){
        printf("\n%c",str[i]);
     } 
     char str2[5] = "calc";//自动补 '\0' 
     int j =0;
     for(;j<5;j++){
        printf("\n%c",str2[j]);
     }
     //两个printf相比,下面的多打一个空的  
    return 0;
}

int main07(void)
{
Stu *s1 = NULL;
Stu p = { 20, “nihao”,”sada” };
s1 = &p; //这里的小心写法,给结构体指针变量全部赋值。(不能够写成 *s1 = p
,原因
*s1是现已上马取结构体的内容,因为s1未有赋值,约等于野指针,不可能取值);

3.3 字符串指针的操作

#include <stdio.h>
#include <stdlib.h>  
int main(int argc, char *argv[]) { 
    char *str = "I Love China";
    str += 5;
    while(*str){
        putchar(str[0]);
        str++;
    } 
    return 0;
    //e China 
}

printf(“%d, %s, %s\n”, s1->age, s1->name, s1->p);

3.4 二维数组

#include <stdio.h>
#include <stdlib.h>  
int main(int argc, char *argv[]) { 
     char str[4][10] = {"notepad","mspaint","mstsc","draw"};
     int i =0;
     for(;i<4;i++){
        printf("\n%s",str[i]); 
     }      
     return 0; 
}

printf(“\n”);
system(“pause”);
return 0;
}

3.5指针修改字符串

#include <stdio.h>
#include <stdlib.h>  
int main(int argc, char *argv[]) { 
     char str[10] ="taskoist";
     char *p = str;
     p = p+4;
     *p ='l';
     system(str); //“tasklist”
     return 0; 
}

3.6 接受输入

#include <stdio.h>
#include <stdlib.h>  
int main(int argc, char *argv[]) {  
      char str[20];//开辟内存空间
      char *p = str;
      scanf("%s",p);//接受输入
      printf("\n%s",p); 
      system(p); 
      return 0; 
}

#include <stdio.h>
#include <stdlib.h>  
int main(int argc, char *argv[]) {  
      char *p =  malloc(sizeof(char)*20);
      scanf("%s",p);//接受输入
      printf("\n%s",p); 
      system(p); 
      return 0; 
}

3.7 常量独有在开首化的时候能够赋值,变量在另外时候都足以赋值

#include <stdio.h>
#include <stdlib.h>  
int main(int argc, char *argv[]) {
       //str是常量,只有在初始化的时候可以被赋值  
       char str[20] ="ipconfig";
//     char st[20];
//     st="ipconfig"; //报错  

       //p是指针变量,可以随时赋值
       char *p = "tasklist";
       char *q;
       q = "tasklist";
       //*q = "tasklist"; //报错  *q是去一个char的值,  tasklist本质是一个指针 
       printf("\n %c ",*q); //t
          printf("\n %s ",q);//tasklist
//     system(q);  
       return 0; 
}

3.8自定义字符串工具类

自定义字符串工具类

4. 数据类型

4.1数组做函数参数会落后为指针

在样式参数里面出现的char buf[30]或者int
a[10]等,编写翻译器会将他视为指针,不会为其积极的多分配内存。

void func(int a[10]){
     printf("\n%d",sizeof(a));//4
} 

int main(int argc, char *argv[]) {
    int a[10];
    printf("\n%d",sizeof(a));//40
    func(a);
    return 0;
}

4.2数据类型的面目

4.2.1数据类型能够精通为创立变量的模子:是长久内部存款和储蓄器大小的外号。

4.2.3数据类型的职能:编写翻译器预算变量分配的内部存款和储蓄器空间的大小。

4.3变量:既可以读又能写的内存对象称为变量,一旦伊始化之后不能够改改的指标称为常量。

变量的实质是:一段连接内部存款和储蓄器空间的小名。
程序通过变量来申请和命名内部存款和储蓄器空间,通过变量名访谈内部存款和储蓄器空间。

4.4

char *p = NULL;//栈区
p = malloc(100);//堆区

4.5

栈区:由编写翻译器自动分配内部存款和储蓄器,存放函数的参数,局地变量的值等
堆区:平日由技术员分配和假释(动态内部存款和储蓄器申请与自由),若工程师不自由,程序甘休时或然由系统回收
全局区:全局变量和静态变量存款和储蓄在这一块,最早化的全局变量和静态变量在一块,未初始化的全局变量和静态变量在隔壁的另一块,该区域在前后相继甘休后由系统回收。
前后相继代码区:寄存函数体的二进制代码。
上边代码中pa,pb相等,字符串存款和储蓄在常量区,一样的字符串编写翻译器只会创设叁个

char *getStra(){
    char *pa = "abcd";
    return pa;
} 

char *getStrb(){
    char *pb = "abcd";
    return pb;
}


int main(int argc, char *argv[]) {
    char *pa = getStra();
    char *pb = getStrb();
    printf("\npa=%x",pa);
    printf("\npb=%x",pb);
    return 0;
}

4.6c语言能够在栈区分配内部存款和储蓄器

下边这段代码中buf[30]是在栈区分配的内部存款和储蓄器,在函数推行完结之后,内部存款和储蓄器就被回收了,所以即使回到了地址,但内存已经清空是无效的。
主调函数分配的内部存款和储蓄器都足以在被调用函数中央银行使,不过被调函数里面分配的内部存款和储蓄器若是在栈区,主调用函数是不可能动用的。

char * getStr(){
    char buf[30];
    strcpy(buf,"abcdef");
    return buf;
}

5. void类型的效果:对函数重返的限定 和对函数参数的限量

另外类型的指针都足以从来赋值给void*,不必要进行强制类型转变

5.1纵然函数未有重回值,那么应注脚为 void 类型

上边这段程序编写翻译和平运动行都不曾难题

add(int a,int b){
    return a+b;
}

int main(int argc, char *argv[]) {

       printf("%d",add(2,3));
       return 0; 
}

结论:在C语言中,凡不加重返值类型限定的函数,就可以被编写翻译器作为重临整型值管理。但是过多程序员却误感觉其为void类型
因此,为了制止混乱,在编写C/C++程序时,对于任何函数都必需二个不漏地钦命其项目。假设函数未有重临值,一定要评释为void类型。那既是前后相继能够可读性的急需,也是编制程序规范性的渴求。另外,加上void类型评释后,也足以表明代码的“自注释”功用。代码的“自注释”即代码能和睦注释本身

5.2尽管函数未有参数,应该证明参数为void

上面这段代码在c中编写翻译运转未有其他难题
表达:在C语言中,能够给无参数的函数字传送送任性档次的参数
可是在c++境况下编写翻译会出难题
由此,无论在C照旧C++中,若函数不接受任何参数,必须要指明参数为void。

int func(){
    return 1;
}

int main(int argc, char *argv[]) {
    printf("%d",func(1));
    return 0;
}

上面这段代码会并发编写翻译错误,因为早就宣示了函数参数类型

int func(void){
    return 1;
}

int main(int argc, char *argv[]) {
    printf("%d",func(1)); //[Error] too many arguments to function 'func'
    return 0;
}

5.3小心使用void类型指针

ANSI标准规定:不能对void类型指针举行算法操作那是因为:进行算法操作的指针必须是规定知道其针对性数据类型大小的

5.4只要函数的参数可以是即兴档次指针,那么应评释其参数为void *

金榜题名的如内部存款和储蓄器操作函数memcpy和memset的函数原型分别为:
  void * memcpy(void *dest, const void *src, size_t len);
  void * memset ( void * buffer, int c, size_t num );
  那样,任何类型的指针都得以流传memcpy和memset中,那也真正地突显了内部存款和储蓄器操作函数的含义,因为它操作的对象只是是一片内部存储器,而不论是这片内部存款和储蓄器是怎么项目。假若memcpy和memset的参数类型不是void\
*,而是char
*,这才叫真正奇异了!那样的memcpy和memset鲜明不是二个“纯粹的,脱离低等乐趣的”函数!
  上边包车型客车代码实践正确:
  //示例:memset接受大肆档案的次序指针
  int intarray[100];
  memset ( intarray, 0, 100*sizeof(int) ); //将intarray清0
  //示例:memcpy接受放肆等级次序指针
  int intarray1[100], intarray2[100];
  memcpy ( intarray1, intarray2, 100*sizeof(int) );
//将intarray2拷贝给intarray1
  风趣的是,memcpy和memset函数再次来到的也是void *类型

5.5 void不能够代表叁个忠实的变量

上面代码都妄图让void代表叁个实打实的变量,因而都以荒唐的代码:
  void a; //错误
  function(void a); //错误
  void展现了一种浮泛,这几个世界上的变量都是“有品种”的

6.结构体

6.1 结构体定义

//自定义类型,数据类型:固定大小内存块的别名 
typedef struct _Teacher{
    char name[62];
    int age;
    char title[32];
}Teacher;


int main(int argc, char *argv[]) {
    printf("%d",sizeof(Teacher));//100  结构体变量内存4字节倍数存放 
    Teacher ta;
    struct _Teacher tb; 
    return 0;
}

6.2结构体使用

//自定义类型,数据类型:固定大小内存块的别名 
typedef struct _Teacher{
    char name[62];
    int age;
    char title[32];
}Teacher;


int main(int argc, char *argv[]) { 
    Teacher ta = {"zhangjingli",25,"Senior"};
    Teacher *p = NULL;
    p = &ta;
    printf("\n%s",ta.name); //第一种 
    printf("\n%s",p->name); //第二种 
    return 0;
}

6.4结构体指针

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

typedef struct _Teacher{
    char name[62];
    int age;
    char title[32];
} Teacher;

Teacher* createArr(int num){
     int i = 0;
     Teacher* parr = (Teacher*)malloc(num*sizeof(Teacher));
     if(parr==NULL){
        printf("\n 分配内存失败");
     }
     for(;i<num;i++){
        memset(parr+i,0,sizeof(Teacher));
        Teacher *t = parr+i;
        t->age  = i*i;
     }
     return parr;
}




int main(int argc, char *argv[]) { 
    Teacher *t = createArr(4);
    printf("%3d",t[3].age);
    free(t);
    return 0;
}

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

struct Teacher{
    char name[62];
    int age;
    char title[32];
};


void printArr(struct Teacher *t,int num){
    int i = 0;
    for(i=0;i<num;i++){
        printf("%4d",t[i].age);
    }
}


void sortArr(struct Teacher* t,int num){
    int i=0;
    int j = 0;
    struct Teacher temp;
    for(i=0;i<num;i++){
        for(j=i+1;j<num;j++){
            if(t[i].age<t[j].age){
                temp = t[i];
                t[i] = t[j];
                t[j] = temp;
            }
        }
    } 
}



int main(int argc, char *argv[]) { 
    int i = 0;
    struct Teacher tArr[10];
    for(i=0;i<4;i++){
        scanf("%d",&tArr[i].age);
    }
    printArr(tArr,4);
    sortArr(tArr,4);
    printArr(tArr,4);
    return 0;
}

6.5组织体内的一流指针

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Teacher{
    char name[62];
    int age;
    char *title;
};

struct Teacher* createArr(int num){
     int i =0;
     struct Teacher* tarr = (struct Teacher*)malloc(num*sizeof(struct Teacher));
     for(;i<num;i++){
         memset(&tarr[i],0,sizeof(struct Teacher));
         memset(tarr+i,0,sizeof(struct Teacher));
         tarr[i].title = (char *)malloc(128*sizeof(char));
         memset(tarr[i].title,0,128*sizeof(char));
     } 
     return tarr;
}

void freeArr(struct Teacher *tarr,int num){
    int i = 0;
    if(tarr==NULL){
        return ;
    }
    for(;i<num;i++){
        char *p = tarr[i].title;
        if(p!=NULL){
            free(p);
        }
        //p需要手动释放name不需要 
    }
    if(tarr!=NULL){
        free(tarr); 
    }
}


int main(int argc, char *argv[]) { 
    struct Teacher *t = createArr(4);
    freeArr(t,4);
    return 0;
}

6.6 结构体内二级指针

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Teacher{
    char name[62];
    int age;
    char *title;
    char **stuname;
};

struct Teacher * createArr(int num){
    int i=0;
    int j=0;
    struct Teacher* p =(struct Teacher*)malloc(num*sizeof(struct Teacher));
    if(p==NULL){
        printf("\n分配内存失败");
    }
    for(i=0;i<num;i++){
        memset(&p[i],0,sizeof(struct Teacher));
        memset(p+i,0,sizeof(struct Teacher));
        p[i].title = (char*)malloc(128*sizeof(char));
        memset(p[i].title,0,128*sizeof(char));
        {
            char **p2 = (char**)malloc(3*sizeof(char *));
            for(j=0;j<3;j++){
                p2[j] = (char *)malloc(128*sizeof(char));
                memset(p2[j],0,128*sizeof(char)); 
            }
            p[i].stuname = p2;
        }
    }
    return p;
} 



int main(int argc, char *argv[]) { 
    struct Teacher *t = createArr(4);

    return 0;
}

6.7浅拷贝

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Teacher{
    char name[62];
    int age;
    char *title;

}; 

int main(int argc, char *argv[]) { 
    struct Teacher ta;
    struct Teacher tb;
    ta.age = 11;
    ta.title = (char*)malloc(128*sizeof(char));
    strcpy(ta.title,"xihe");
    tb = ta;//机械拷贝,将ta中title的首地址分配到tb的title
    //也就是ta tb的title指向同一块内存区域
    //下面的代码会使同一块内存被释放两次
    //运行会报错 
    if(ta.title!=NULL){
        free(ta.title);
        printf("\n free ta.title");
    }

    if(tb.title!=NULL){
        free(tb.title);
         printf("\n free ta.title");
    } 
    return 0;
}

6.8深拷贝

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Teacher{
    char name[62];
    int age;
    char *title;

}; 

//深拷贝
//为对象又开辟了一块新的内存空间 
void copyObj(struct Teacher* from,struct Teacher* to){
    memcpy(to,from,sizeof(struct Teacher));
    to->title = (char*)malloc(128);
    to->age = from->age;
    strcpy(to->title,from->title);
}


int main(int argc, char *argv[]) { 
    struct Teacher ta;
    struct Teacher tb;
    ta.age = 11;
    ta.title = (char*)malloc(128*sizeof(char));
    strcpy(ta.title,"xihe");
    copyObj(&ta,&tb);
    //ta和tb的title指向两个不同的内存空间,释放两次不会报错 
    if(ta.title!=NULL){
        free(ta.title);
        printf("\n free ta.title");
    }

    if(tb.title!=NULL){
        free(tb.title);
         printf("\n free ta.title");
    } 
    return 0;
}

6.9 结构体的作用大约也正是java里的类

6.10 链表的兑现

#ifndef LIST_H
#define LIST_H

typedef struct ListElmt_{
    void *data;
    struct ListElmt_ *next;
}ListElmt;


typedef struct List_{
    int size;
    int (*match)(const void *key1,const void *key2);
    void (*destroy)(void *data);
    ListElmt *head;
    ListElmt *tail;
}List;

void list_init(List *list,void(*destroy)(void *data));
void list_destroy(List *list);
int list_ins_next(List *list,ListElmt *element,const void *data);
int list_rem_next(List *list,ListElmt *element,void **data);

#define list_size(list) ((list)->size)
#define list_had(list) ((list)->head)
#define list_tail(list) ((list)->tail)
#define list_is_tail(list,element) ((element)==(list)->tail?1:0)
#define list_is_head(list,element) ((element)==(list)->head?1:0)
#define lsit_data(element) ((element)->data)
#define list_next(element) ((element)->next)

#endif

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

void list_init(List *list,void (*destroy)(void *data)){
    list->size = 0;
    list->destroy = destroy;
    list->head = NULL;
    list->tail = NULL;
}

void list_destroy(List *list){
    void *data;
    while(list_size(list)>0){
        if(list_rem_next(list,NULL,(void  **)&data)==0 && list->destroy!=NULL){
            //调用一个用户自定义的函数释放资源
            list->destroy(data); 
        }
    }
    memset(list,0,sizeof(list));
    return;
}

//在指定元素element后插入新的元素 
int list_ins_next(List *list,ListElmt *element,const void *data){
    //创建新的元素
    ListElmt *newElement;
    if((newElement=(ListElmt*)malloc(sizeof(ListElmt)))==NULL){
        return -1;
    } 
    newElement->data = data;

    if(element==NULL){
        if(list_size(list)==0){
            list->tail = newElement;
        }
        newElement->next = list->head;
        list->head = newElement;
    } else{
        if(element->next == NULL){
            list->tail = newElement;
        }
        newElement->next = element->next;
        element->next = newElement; 
    }
    list->size++;
    return 0;
}

int list_rem_next(List *list,ListElmt *element,void **data){
    ListElmt *oldElement;
    if(list_size(list)==0){
        return -1;
    }
    if(element==NULL){
        *data = list->head->data;
        oldElement = list->head;
        list->head = list->head->next;
        if(list_size(list)==1){
            list->tail = NULL;
        }
    }else{
        if(element->next == NULL){
            return -1;
        }
        *data = element->next->data;
        oldElement = element->next;
        element->next = element->next->next;
        if(element->next == NULL){
            list->tail = element;
        }
    }
    free(oldElement);
    list->size--;
    return 0;
}

6.11 指向结构体的指针的三种格局

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

struct Info{
int num;
float score;
};

int main()
{
    struct Info info;
    struct Info *pinfo = &info;
    struct Info *p = (struct Info *)malloc(sizeof(struct Info));
    printf("Hello world!\n");
    return 0;
}

7.函数

7.1函数能够嵌套使用

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

int add(int a,int b){
    return a+b;
}

int main()
{ 
    int result = add(3,add(3,3)); 
    printf("%d",result);//9
    return 0;
}

7.2递归

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

void dosth(int num){
    if(num==0){
        return;
    }else{
       printf("\n do");
       dosth(num-1);
    }
}

int main()
{
    dosth(5);
    return 0;
}

//利用递归求累加和
#include <stdio.h>
#include <stdlib.h>
int add(int n){
    if(n==1){
        return 1;
    }else{
        return add(n-1)+n;
    }
}

int main()
{
    printf("\n %d",add(100));//5050
    return 0;
}

7.3 50级阶梯的走法

走到第一层的时候 1种
走到第二层的时候依旧走一回,要么走一遍 2种
走到第三层的时候 3种
四 (1111 22 211 112 121) 5种
。。。。。。。。。。。。。。。。。。 前二种只和 f(n) = f(n-1) + f(n-2)

//耗时很长,递归效率低
#include <stdio.h>
#include <stdlib.h>
int tecent(int n){
  if(n==1){
    return 1;
  }else if(n==2){
     return 2;
  }else{
    return tecent(n-1)+tecent(n-2);
  }
}

int main()
{
    printf("\n %d",tecent(80));//
    return 0;
}

//很快得到结果
#include <stdio.h>
#include <stdlib.h>
int tecent(int n){
   int n1=1;
   int n2=2;
   int n3=0;
   int i=0;
   for(;i<n;i++){
    n3 = n1 +n2;
    n1 = n2;
    n2 = n3;
   }
   return n3;
}

int main()
{
    printf("\n %d",tecent(80));//
    return 0;
}

#include <stdio.h>
#include <stdlib.h>
int tecent( ){
    int a[50];
    a[0]=1;
    a[1] = 2;
    int i=2;
    for(;i<20;i++){
        a[i] = a[i-1]+a[i-2];
    }
    return a[19];
}

int main()
{
    printf("\n %d",tecent( ));//
    return 0;
}

7.4函数参数的次第从右向左

#include <stdio.h>
#include <stdlib.h>
void show(int a,int b){
    printf("\n %d,%d",a,b);
}

int add(int a,int b){
   printf("\n %d,%d",a,b);
   return a+b;
}

int main()
{
    show(add(1,2),add(3,4));//3,4  1,2  3,7
    //先打印 3 4 函数参数的顺序从右向左
    return 0;
}

#include <stdio.h>
#include <stdlib.h>
void show(int a,int b){
    printf("\n %d,%d",a,b);//100 100
}



int main()
{
    int num = 99;
    show(num,++num);
    return 0;
}

7.5 数组做参数未有别本机制,数组做参数退化为指针

#include <stdio.h>
#include <stdlib.h>
void test(int a[10]){
    printf("\n %d",sizeof(a));//4
}

void changearr(int a[10]){
    int i = 0;
    for(;i<10;i++){
        a[i]+=11;
    }
}


int main()
{
    int i = 0;
    int a[10] = {1,2,3,4,5,6,7,8,9,0};
    test(a);
    changearr(a);
    for(;i<10;i++){
        printf("\n %3d",a[i]);// 12 13 14 15 16 17 18 19 20 11
        //这里数组的元素都发生了改变,说明在changearr函数中并没有产生副本,如果产生副本值就不会发生改变了
    }
    return 0;
}

7.6 return 的别本机制,return的别本在寄放器

#include <stdio.h>
#include <stdlib.h>
int go(){
    int a = 3;//auto变量,go函数执行完之后就销毁了
    return a;//副本,在寄存器
}


int main()
{
    printf("\n %d",go()); // 3
 //   printf("\d %x",&go()); 函数的返回值不能取地址
    return 0;
}

7.7赋值表明式的值等于被赋值的变量的值

#include <stdio.h>
#include <stdlib.h>
struct Info{
    int num;
    float score;
};


int main()
{
    struct Info info;
    printf("%d,%f",info.num=1,info.score=8);//1  8.00000
    return 0;
}

7.8函数名是常量指针

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

int add(int a ,int b){
return a+b;
}

int sub(int a,int b){
    return a-b;
}
int main()
{
    int(*p)(int,int);
    p = add;
    printf("\n %d",p(1,2));//3
    p = sub;
    printf("\n %d",p(5,1));//4
    return 0;
}

7.9函数指针数组

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

int add(int a ,int b){
return a+b;
}

int sub(int a,int b){
    return a-b;
}

int mul(int a,int b){
    return a*b;
}

int divide(int a,int b){
    return a/b;
}

int main()
{
    int(*p[4])(int ,int )={add,divide,sub,mul};
    int i =0;
    for(;i<4;i++){
        printf("%5d",p[i](10,2));
    }
    return 0;
}

8 内存

8.1证明能够有三个实体只好有多少个

注明只是用来证明存在,定义是在内部存款和储蓄器中开荒实体(一人得以有三个身份ID号,不过真正的人不得不有二个)

//这段代码没有问题
#include <stdio.h>
#include <stdlib.h>
int a;
int a; 
int main()
{ 
    return 0;
}

//这段代码有问题
#include <stdio.h>
#include <stdlib.h> 
int main()
{
    int a;
    int a;
    return 0;
}

8.2常量字符串在代码区

#include <stdio.h>
#include <stdlib.h>
int main()
{
    char *p ="ABCDEFG";
    printf("%d,%d",sizeof(p),sizeof("ABCDEFG"));//4 8
    printf("\n %p",&p);
    printf("\n %p",p);
    //*p = 'a';  //代码区只能读,常量字符串在代码区
    return 0;
}

8.3 三种常量的分别

#include <stdio.h>
#include <stdlib.h>
#define N 10  //N存储在cpu上
const int num = 10;
int main()
{
   // int *p = &N;//不能取地址
    int *q = #//可以取地址
    //N = 3;//在cpu上没有在内存上,不能当左值
    //num = 4;//在内存上,但是被const修饰,不能修改
    return 0;
}

8.4 c语言的const是伪常量,只可以制止间接赋值的修改,通过指针还是得以修改的。

8.5 静态局地变量在编写翻译的时候就开端化了,

int main()
{
    int i =0;
    for(;i<10;i++){
        int a = 10;//用完就回收
        static int b= 10;//与程序共存亡,静态局部变量,编译的时候就初始化了
        a+=1;
        b+=1;
         printf("a=%d,b=%d\n",a,b);//a永远都是11,b是11 12 13 14.。。。
    } 
    return 0;
}

Leave a Comment.