【C语言】常用总结

总结

基础

  • 程序结构是三种: 顺序结构、选择结构(分支结构)、循环结构。
  • 读程序都要从main()入口,然后从最上面顺序往下读(碰到循环做循环,碰到选择做选择),有且只有一个main函数。
  • 计算机的数据在电脑中保存是以二进制的形式,数据存放的位置就是他的地址。
  • bit是位,指为0或1。byte是指字节,一个字节=八个位。
  • 每个C语言程序写完后,都是先编译,后链接,最后运行。(.c→.obj→.exe)这个过程中注意.c 和.obj 文件是无法运行的,只有.exe文件才可以运行。

常考

  • 编译预处理不是C语言的一部分,不占运行时间不要加分号
    C语言编译的程序称为源程序,它以ASCII数值存放在文本文件中。
  • #define PI 3.1415926; 这个写法是错误的,一定不能出现分号
  • 每个C语言程序中main函数是有且只有一个。
  • 在函数中不可以再定义函数。
  • 算法:可以没有输入,但是一定要有输出。
  • break可用于循环结构和switch语句。
  • 逗号运算符的级别最低,赋值的级别倒数第二。
  • int *p 中 *p 和 p 的差别:简单说*p 是数值,p 是地址
    • *p:可以当做变量来用;*的作用是取后面地址 p 里面的数值。
    • p:是当作地址来用。可以用在 scanf 函数中:scanf("%d",p);
  • *p++ 和 (*p)++的之间的差别:(笔试重点)
    • *p++:地址会变化。
      口诀:取当前值,然后再移动地址!
    • (*p)++:数值会要变化。
      口诀:取当前值,然后再使数值增加 1。

      例题:int *p,a[]={1,3,5,7,9};
      p=a;
      请问*p++和(*p)++的数值分别为多少?
      *p++:这个本身的数值为1。由于是地址会增加一,所以指针指向数值3了。
      (*p)++:这个本身的数值为1。由于++表示数值会增加,指针不移动,但数值1由于自加了一次变成了2。

  • 二级指针:
    • *p:一级指针:存放变量的地址。
    • **q:二级指针:存放一级指针的地址。

      常考题目:int x=7; int *p=&x,**q=p;
      问你:*p 为多少?*q为多少?**q为多少?
      *p=7,*q=p,**q=7
      再问:**q=&x 的写法可以吗?不可以,二级指针只能存放一级指针的地址。

  • 程序进行编译时,并不为形式参数分配存储空间。只有在被调用时形式参数才临时地占有存储空间
    形式参数(形参)存储类别默认“auto”
    形参用关键字auto作存储类别的声明时,关键字“auto”可以省略,auto 不写则隐含确定为“自动存储类别”,它属于动态存储方式。
  • 函数的存储类型是函数定义时函数名前面的数据类型前面的存储类型。
    函数的存储类型默认“extern”,表示该函数属外部函数(即 可以被本 C 文件外的其他 C 源程序文件中的函数调用
    • extern:(External)
      整个工程可见,其他文件可以使用extern外部声明后直接使用。也就是说其他文件不能再定义一个与其相同名字的变量了(否则编译器会认为它们是同一个变量)
    • static:代表静态全局
      仅对当前文件可见,其他文件不可访问,其他文件可以定义与其同名的变量,两者互不影响。

重点

  • strlen 和 sizeof 的区别(重点):
    • sizeof:(求实际存储空间
      相当于是个宏一样的东西,因为它只是一个运算符,而不是函数,编译时展开为常数,编译的时候有每个变量的定义表sizeof通过查表确定变量占用的空间,这是分配内存给process 之前要确定的。
      其实可以简单的理解sizeof针对"类型"的,而非"变量",但此时不能这样看,如:
      sizeof("HELLO");括号中不是字符数组const char *,而是一个"字符串",所以结果大小为 5。
      字符数组:

      char *ps = "HELLO"; //字符数组
      sizeof(ps) = 4  //只是指针的大小,即 地址(整数类型占4个字节)
      sizeof(*ps) = 1 //*ps+0代表数组第一个元素的大小,即ps[0]
      
      char as[8];
      sizeof(as) = 8  //因为as的类型为 char [8],这个大小的确是8
      sizeof(*as) = 1 //*as+0代表数组第一个元素的大小,即as[0]
      
      char aa[8][9];
      sizeof((char *)aa) = 4  //还是 char *
      
      char arr[100] = "HELLO";
      sizeof(arr) = 100   //和赋什么值没什么关系,关键是"类型"是什么
      
      int func(char p[100]) {
          sizeof(p) = 4;  //C/C++中不能传数组,只能传指针,所以任何数组都会隐式转成指针形式进行操作。
      }
    • strlen:(求字符串长度,即 字符个数,不包括结束符)
      它是一个函数,参数是 const char*,搞清楚它的实现,就是碰到'\0'(字符串结尾,就停止计数,但不包括'\0')。所以它不是看类型而是看变量,取决于变量赋的什么值。

  • 函数的递归一定会考。
  • 两种重要的数组长度:
    char a[]={'a','b','c'}; 数组长度为3,字符串长度不定(因为没有'\0'结束符)。sizeof(a)为3。
    char a[5]={'a','c'}; 数组长度为5,字符串长度3。sizeof(a)为5。
    char a[]={'a','c'}; 这是一个字符数组,占3个字节
    char a[]="abc"; 则不同,它是一个字符串,最后还有一个'\0'结束符,占4个字节

  • scanf 和 gets 的区别:
    如果输入的是 good good study!
    • scanf("%s",a);
      只会接收 good。

      考点:不可以接收空格。(遇到空格或回车就终止)

    • gets(a);
      会接收 good good study!

      考点:可以接收空格。(遇到回车终止)

  • 指针考点:
    char ch[]="iamhandsome";
    char *p=ch;
    问你:*(p+2) 和 *p+2 的结果是多少?
    *(p+2) = 'm',*p+2 = 'k'

    解析:
    第一个是地址+2,所以取m;
    第二个则是数值+2,即 ASCII码值+2,ijk,所以取k。

  • 字符串的赋值:
    C语言中没有字符串变量,所以用数组和指针存放字符串:
    1. char ch[10]={"abcdefgh"};
    2. char ch[10]="abcdefgh";
    3. char ch[10]={'a','c','d','e','f','g','h'};
    4. char *p="abcdefgh";
    5. char *p;
    6. ch="abcdefgh"; !数组名不可以赋值!(只能一个一个循环赋值)
    7. char *p={"abcdefgh"}; !大括号是数组用的,相当于集合,而指针类型不能用大括号
  • 逗号表达式:
    将两个及其以上的式子联接起来,从左往右逐个计算表达式,整个表达式的值为最后一个表达式的值
    (2,4)的表达式的数值就是4。
    z = (2,4);(整个是赋值表达式),这个时候z的值为4。
    z = 2,4; (整个是逗号表达式,即 (z = 2),(3),(4);),这个时候z的值为2,这个(z = 2,4)式子的值为4。

    用途:for(i=0,j=0; i<10; i++),像这样联接式子,因为for中的每个区域只能放一个式子,所以需要逗号表达式联接多个式子。

宏定义defind

问题:#define f(x) (x\*x)#define f(x) x\*x 之间的差别。

define是C语言中的宏定义关键字,其定义格式如下:

#define [MacroName] [MacroValue]宏定义分为普通宏定义和带参数的宏定义

  • 普通宏定义:#define PI (3.1415926)

  • 带参数的宏定义 (宏函数):#define max(a,b) ((a)>(b)? (a),(b))

    注意:变量在宏中要用括号括起来
    因为,在C语言中define宏定义在编译时,会被展开,进行“傻瓜式”替换,也称为“字面”替换,如果没有括号有可能会产生歧义。

    如:

    int a,b,c,d,e;
    a=1; b=2; c=6; d=4;
    e = f(a+b)*f(c+d) ;  //理论值e=9*100=900
    
    #define f(x) (x*x)
    替换结果为:e =(a+b*a+b)*(c+d*c+d) = 5*34=170
    
    #define f(x) x*x 
    替换结果为:e = a+b*a+b*c+d*c+d=1+2+12+24+4=43
    
    #define f(x) ((x)*(x))
    替换结果为:e = ( (a+b)*(a+b)*(c+d)*(c+d) )=3*3*10*10=900

    这个才是我们想要的结果!

字符

  • 字符数据的合法形式:
    '1' 是字符占一个字节,"1"是字符串占两个字节(含有一个结束符号)。
    '0' 的 ASCII 数值表示为 48,'A'的 ASCII 数值是 65,'a' 的 ASCII 数值是 97,
    一般表示单个字符错误的形式:'65' "1"
    字符是可以进行算术运算的,记住:'0'-0=48

    注意:这个48不用记,用的时候直接'0'-0,就可以转换字符和数字了。
    记忆:0Aa:486597,486 看 re0 的应该知道,597 就是486+111。

  • 大写字母和小写字母转换的方法:
    'A'+32='a' 相互之间一般是相差32。

    注意:这个32不用记,要用的时候直接'a'-'A',就可以得出转换大小写的数值了。
    在ASCII码表中,A比a先,所以ASCII码小
    类比:A比a先,所以生日年份比a小。

  • 字符型和整数是近亲:两个具有很大的相似之处
    char a = 65;
    printf("%c",a); 得到的输出结果:a
    printf("%d",a); 得到的输出结果:65

转义字符

转义字符分为一般转义字符、八进制转义字符、十六进制转义字符。

  • 一般转义字符:\0、 \n、 \'、 \"、 \\。
  • 八进制转义字符'\ddd':(其中d为常数,ddd表示三位8进制数)(以0开头的表示八进制)
    '\141'=97 是合法的, 前导的0是不能写的。
  • 十六进制转义字符'\xhh':(其中h为常数,hh表示两位16进制数)(以0x开头的表示十六进制)
    '\x6d'=109 才是合法的,前导的0不能写,并且x是小写。
进制名称 英文 缩写
二进制 Binary B
八进制 Octal O
十进制 Decimal D
十六进制 Hexadecimal H

输入输出

格式符

格式说明 表示内容 注释
%d 整型十进制 int Decimal
%ld 长整型 long int Long Decimal
%f 浮点型 float Float
%lf 双精度浮点型 double Long Float
%% 输出一个百分号 %
%c 字符 char Char
%s 字符串 String
%o 八进制 Octal
%#o 带前导(0)的八进制
%x 十六进制 Hexadecimal
%#x 带前导(0x)的十六进制
%p 指针的值,输出地址符
即 地址
Pointer
%md 整型,m总长度(常数)(默认为正数+) 右对齐数轴左-右+
即 不足的话,左边补上空格
%-md 整型,m总长度(常数)(负数- 左对齐
即 不足的话,右边补上空格
%m.nf 浮点型
m总字符长度(包含小数点)
n小数长度
要进行四舍五入
当实际的显示大于m,那就按实际输出,也就是m无意义了
%3d 对应 1234 的话,就是1234 没有空格

举例说明:
printf("%2d",123); 第二部分有三位,大于指定的两位,原样输出 123
printf("%5d",123); 第二部分有三位,小于指定的五位,左边补两个空格 123
printf("%10f",1.25); 小数要求补足 6 位的,没有六位的补 0,。结果为 1.250000
printf("%5.3f",125); 小数三位,整个五位,结果为 1.250(小数点算一位
printf("%3.1f",1.25); 小数一位,整个三位,结果为 1.3(要进行四舍五入

输入

要特别注意的是:
scanf("%d,%d",&x,&y);
scanf 的第二个部分一定要是地址!

  • 指定输入的长度:(一般用空格或回车进行间断)
    终端输入:1234567
    scanf("%2d%4d%d",&x,&y,&z); x 为 12,y 为 3456,z 为 7
    终端输入:1 234567 由于 1 和 2 中间有空格,所以只有 1 位给 x
    scanf("%2d%4d%d",&x,&y,&z); x 为 1,y 为 2345,z 为 67

  • 字符和整型是近亲:
    int x=97;
    printf("%d",x); 结果为 97
    printf("%c",x); 结果为 a

  • 输入时候字符和整数的区别:
    scanf("%d",&x); 这个时候输入 1,特别注意表示的是整数 1
    scanf("%c",&x); 这个时候输入 1,特别注意表示的是字符'1',ASCII 为整数 49。

  • %*d
    • scanf("%d%d%*d%d",&a,&b,&c); 跳过输入的第三个数据
      输入:1 2 3 4
      即 a=1,b=2,c=4
    • printf("%*d",len,a); 将整数a按len个字符的宽度显示。
      *号告诉printf待打印字符的显示宽度从后面的参数列表中提取,指定是多少就按多少个字符宽度显示。
      printf("%5d",a); 将整数a按5个字符的宽度显示。
  • x保留n位小数,第n+1位四舍五入:((int)\((x*10^n+0.5)/10.0^n\)
    y=(int)(x*100+0.5)/100.0 这个保留两位小数,对第三位小数四舍五入
    y=(int)(x*1000+0.5)/1000.0 这个保留三位小数,对第四位小数四舍五入
    y=(int)(x*10000+0.5)/10000.0 这个保留四位小数,对第五位小数四舍五入

    这个有推广的意义,注意 x = (int)x 这样是把多余的小数部分去掉。
    注意:这个只去掉了分子的小数部分,把分子化为了整型,当除以分母时,又恢复了浮点型。

基本表达式

注意:C 语言中是用非 0 表示逻辑真,用 0 表示逻辑假。

  • 逗号表达式:
    将两个及其以上的式子联接起来,从左往右逐个计算表达式,整个表达式的值为最后一个表达式的值
    (2,j=0; i<10; i++),像这样联接式子,因为for中的每个区域只能放一个式子,所以需要逗号表达式联接多个式子。

  • 赋值表达式:(可以连续赋值)
    1. 计算赋值运算符右侧表达式的值。(“=”为赋值运算符)
    2. 将赋值运算符右侧表达式的值赋给左侧的变量。
    3. 将赋值运算符左侧的变量的值作为表达式的值。(注意与逗号表达式的右侧区分)

      这就是连续赋值可以的原因。而连续比较大小关系不行,因为它表达式的值是bool类型(即 真假),当连续比较时数值会发生改变(变成0或者1)。
      例如:x=y=3 就相当于 x=(y=3) 结果都为3,这种连续赋值是可以的。
      特别注意:而与之相对的连续关系表达式 1<0<2不行的,这个从数学的角度出发肯定是错的,但是如果是 C 语言那么就是正确的!因为 1<0 为假得到 0,表达式就变成了 0<2 那么运算结果就是 1,为真!

  • 关系表达式:(不能连续比较)
    • 表达式的数值只能为 1(表示真),或 0(表示假)。
      如 9>8 这个关系表达式是真的,所以 9>8 这个表达式的数值就是 1。 如 7<6 这个关系表达式是假的,所以 7<6 这个表达式的数值就是 0
    • 易错:int x=1,y=0,z=2; x<y<z 是真还是假?
      带入为 1<0<2,从数学的角度出发肯定是错的,但是如果是 C 语言那么就是正确的!因为 1<0 为假得到 0,表达式就变成了 0<2 那么运算结果就是 1,为真!
    • 等号和赋值的区别!一定记住"="就是赋值,"=="才是等号。
  • 逻辑表达式:(表达式的数值只能为 1(表示为真),或 0(表示假))
    • 共有 &&、||、! 三种逻辑运算符号。
    • ! > && > || 优先的级别。
    • 表示 x 小于 0 大于 10 的方法:0<x<10 是不行的。
      先计算 0<x 得到的结果为 1 或则 0;再用 0,或 1 与 10 比较得到的总是真(为 1)。所以一定要用 (0<x)&&(x<10)表示比 0 大比 10 小。
    • 注意短路现象。考试比较喜欢考到。

      短路现象:为了要提高效率。在逻辑运算时候,如果值已经能决定整个表达式的值,就不会再往右继续运算了。
      例如:在if里有个&&,如果左边的值为假,就不会再算右边的真假。
      ----------------------------------------------------------------------------------------
      短路现象常见的有,短路与(&&)和短路或(||)(当执行结果已经可以确定,则后面的将不再执行了)
      a && b ,如果a 的值为假,则整个表达式的值就为假,它是从左向右计算的。所以执行该表达式后,b 的值还是它的初始值,即不进行运算。
      a || b ,如果a 的值为真,整个表达式的值就为真,执行顺序同上。b 的真假由最初的真假来判断,也就是说,当a 为真时,b 则不进行运算了。

      例如:(m=a>b)&&(n=c>d),当a b c d 分别为1,2,3,4,m=n=1时,由于 a>b 为0,则m =0。而后面的不再执行,所以n=1而不是0。

  • switch 语句:
    • 执行的流程一定要弄懂!
    • 注意有 break 和没有 break 的差别,
      • 没有 break 时候,只要有一个 case 匹配了,剩下的都要执行
      • 有 break 则是直接跳出了 swiche 语句。
    • switch 只可以和 break 一起用,不可以和 continue 用。
    switch(x) { //(x:是整型常量,字符型常量,枚举型数据)
    case 1: … //Case 中不可以是变量。
    case 2: … 
    }
  • 循环结构:先执行while中的表达式(这样才能判断是否循环)

    注意:不管循环不循环,都要执行while中的表达式才能判断是否循环,不能说一眼看出0--不循环了,就不--了,计算机还是要--的。

    • 1

      int k=1 ;
      while(--k);
      printf("%d",k);

      结果为0

      解析:执行while中的表达式,减1,然后为0(不能循环),终止循环(循环执行次数0),输出0。

    • 2

      int k=1 ;
      while(k--);
      printf("%d",k);

      结果为-1

      解析:执行while中的表达式,取1(可以循环),减1,循环,第二次执行while中的表达式,取0(不能循环),减1,终止循环(循环执行次数1),但是仍然-1了。

函数

函数:是具有一定功能的一个程序块,是 C 语言的基本组成单位。

  • 函数不可以嵌套定义。但是可以嵌套调用。
  • 函数名缺省返回值类型默认为int
  • C 语言由函数组成,但有且仅有一个 main 函数!是程序运行的开始!
  • 函数的参数可以是常量,变量,表达式,甚至是函数调用。

    add(int x,int y){return x+y;}
    main() {
        int sum;
        sum=add(add(7,8),9);
    }
    请问 sum 的结果是多少?
    结果为 24
  • 一定要注意参数之间的传递
    实参和形参之间传数值传地址的差别。
    传数值,形参的变化不会改变实参的变化。
    传地址,形参的变化会有可能改变实参的变化。
  • 函数声明的考查:
    • 函数一定要有:函数名,函数的返回类型,函数的参数类型。
    • 不一定要有:形参的名称。
    int *fun(int a[],int b[]) 
    {
        …………
    }

    已经知道函数是这样。这个函数的正确的函数声明怎么写?
    int *fun(int *a,int *b); 这里是函数声明的写法,注意数组就是指针
    int *fun(int a[],int b[]); 这种写法也是正确
    int *fun(int b[],int c[]); 这种写法也是正确的,参数的名称可以随便写
    int *fun(int *,int *); 这种写法也是正确的,参数的名称可以不写

指针

定义 含义
int i; 定义整型变量 i
int *p; p 为指向整型变量的指针变量
int a[n]; 定义整型数组 a,它有 n 个元素
int *p[n]; 定义指针数组 p,它由 n 个指向整型数据的指针元素组成
int (*p)[n]; p 为指向含有 n 个元素的一元数组的指针变量
int f(); f 为返回整型数值的函数
int *p(); p 为返回一个指针的函数,该指针指向整型数据
int (*p)(); p 为指向函数的指针,该函数返回一个整型值
int **p; p 是一个指针变量,它指向一个指向整型数据的指针变量
  • int *p 中 *p 和 p 的差别:简单说*p 是数值,p 是地址
    • *p:可以当做变量来用;*的作用是取后面地址 p 里面的数值。
    • p:是当作地址来用。可以用在 scanf 函数中:scanf("%d",p);
  • *p++ 和 (*p)++的之间的差别:(笔试重点)
    • *p++:地址会变化。
      口诀:取当前值,然后再移动地址!
    • (*p)++:数值会要变化。
      口诀:取当前值,然后再使数值增加 1。

      例题:int *p,9};
      p=a;
      请问*p++和(*p)++的数值分别为多少?
      *p++:这个本身的数值为1。由于是地址会增加一,所以指针指向数值3了。
      (*p)++:这个本身的数值为1。由于++表示数值会增加,指针不移动,但数值1由于自加了一次变成了2。

  • 二级指针:
    • *p:一级指针:存放变量的地址。
    • **q:二级指针:存放一级指针的地址。

      常考题目:int x=7;int*p=&x,**q=p;
      问你:*p 为多少?*q为多少?**q为多少?
      *p=7,*q=p,**q=7
      再问:**q=&x 的写法可以吗?不可以,二级指针只能存放一级指针的地址。

  • 三名主义:
    • 数组名:表示第一个元素的地址。数组名不可以自加,他是地址常量名。
    • 函数名:表示该函数的入口地址。
    • 字符串常量名:表示第一个字符的地址。
  • 传数值和传地址:

    void fun(int a,int b) {
        int t;
        t=a;a=b;b=t; 
    }
    main() {
        int x=1,y=3; 
        fun(x,y);
        printf("%d,%d",x,y);
    }

    这个题目答案是 1 和 3。
    传数值,fun 是用变量接受,所以 fun 中 的交换不会影响到 main 中的 x 和 y 。
    传数值,形参的变化不会影响实参。

    void fun(int *a,int *b) {
        int t;
        t=*a;*a=*b;*b=t;
    }
    main() {
        int x=1,y=3;
        fun(&x,&y);
        printf("%d,x,y);
    }

    这个题目的答案就是 3 和 1。
    传地址,fun 用指针接受!这个时候 fun中的交换,就会影响到 main 中的 x 和 y。
    传地址形参的变化绝大多数会影响到实参!

  • 函数返回值是地址,一定注意*号。

    int *fun(int *a,int *b) {   //可以发现函数前面有个*,这个就说明函数运算结果是地址 
        if(*a>*b) return a;     //return a 可以知道返回的是 a 地址。
        else return b; 
    }
    main() { 
        int x=7,y=8,*max;
        max = fun(&x,&y); 
        //由于 fun(&x,&y)的运算结果是地址,所以用 max 来接收。
        printf("%d",*max) 
    }

数组

数组:存放的类型是一致的。多个数组元素的地址是连续的。

  • 数组的初始化,一维和二维的,一维可以不写,二维第二个[]一定要写
    int a[]={1,2} 合法。 int a[][4]={2,3,4}合法。 但 int a[4][]={2,3,4}非法。

科普:

  • '0':代表 字符'0',对应ASCII码值为 0x30(也就是十进制的48);
  • '\0':代表 空字符\0(转义字符)(输出为空),对应ASCII码值为 0x00(也就是十进制的0),用作字符串结束符;
  • 0:代表 数字0,若把 数字0 赋值给 某个字符,对应ASCII码值为 0x00(也就是十进制0);
  • "0":代表 一个字符串,字符串中含有 2个字符,分别是 '0' 和 '\0'。

一维数组

  • 当所赋初值少于所定义数组的元素个数时,将自动给后面的元素补以初值0。

    例:给a数组中所有元素赋初值0
    int a[10]={0};

  • 对于字符型数组也同样补以初值 0,即 '\0'。(而不是'0','0'对应的ASCII码为48)
    (C语言中,'\0'表示的空字符,则其对应的ASCII码值为0。)
    (而NULL空指针ASCII码也是0

    例如:
    char c[5]={'@'};
    相当于:
    char c[5]={'@','\0','\0'};

  • 一维数组的初始化:(当所赋初值少于所定义数组的元素个数时,将自动给后面的元素补以初值0。)
    int a[5]={1,2,4,5}; 合法
    int a[5]={1,}; 合法(未设置的部分为0)
    int a[5]={1,3}; 合法
    int a[]={1,5}; 合法,后面决定前面数组的大小!
    int a[5]={1,6}; 不合法,赋值的个数多余数组的个数了
  • 一维数组的定义;
    int a[5]; 定义时数组的个数不是变量一定是常量
    int a[1+1]; 合法,个数是常量 2,是个算术表达式
    int a[1/2+4]; 合法,同样是算术表达式
    int x=5,int a[x]; 不合法,因为个数是 x,是个变量
    #define P 5 int a[P]; 合法,define 后的的 P 是符号常量,只是长得像变量

一维数组的重要概念:

  • 对 a[10]这个数组的讨论。
    • a 表示数组名,是第一个元素的地址,也就是元素 a[0]的地址。(等价于&a)
    • a 是地址常量,所以只要出现 a++,或者是 a=a+2 赋值的都是错误的。
    • a 是一维数组名,所以它是列指针,也就是说 a+1 是跳一列。
  • 对 a[3][3]的讨论。
    • a 表示数组名,是第一个元素的地址,也就是元素 a[0][0]的地址。
    • a 是地址常量,所以只要出现 a++,或者是 a=a+2 赋值的都是错误的。
    • a二维数组名,所以它是行指针,也就是说 a+1 是跳一行。
    • a[0]、a[1]、a[2]也都是地址常量,不可以对它进行赋值操作,同时它们都是列指针,a[0]+1,a[1]+1,a[2]+1 都是跳一列。
    • 注意 a 和 a[0] 、a[1]、a[2]是不同的,它们的基类型是不同的。前者是一行元素,后三者是一列元素。

二维数组

  • 二维数组的初始化
    int a[2][3]={1,6}; 合法,很标准的二维的赋值。
    int a[2][3]={1,}; 合法,后面一个默认为 0。
    int a[2][3]={{1,} {4,6}}; 合法,每行三个。
    int a[2][3]={{1,}{3,5}}; 合法,第一行最后一个默认为 0。
    int a[2][3]={1,6,7}; 不合法,赋值的个数多于数组的个数。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


一.C语言中的static关键字 在C语言中,static可以用来修饰局部变量,全局变量以及函数。在不同的情况下static的作用不尽相同。 (1)修饰局部变量 一般情况下,对于局部变量是存放在栈区的,并且局部变量的生命周期在该语句块执行结束时便结束了。但是如果用static进行修饰的话,该变量便存
浅谈C/C++中的指针和数组(二) 前面已经讨论了指针和数组的一些区别,然而在某些情况下,指针和数组是等同的,下面讨论一下什么时候指针和数组是相同的。C语言标准对此作了说明:规则1:表达式中的数组名被编译器当做一个指向该数组第一个元素的指针; 注:下面几种情况例外 1)数组名作为sizeof的操作数
浅谈C/C++中的指针和数组(一)指针是C/C++的精华,而指针和数组又是一对欢喜冤家,很多时候我们并不能很好的区分指针和数组,对于刚毕业的计算机系的本科生很少有人能够熟练掌握指针以及数组的用法和区别。造成这种原因可能跟现在大学教学以及现在市面上流行的很多C或者C++教程有关,这些教程虽然通俗易懂,
从两个例子分析C语言的声明 在读《C专家编程》一书的第三章时,书中谈到C语言的声明问题,《C专家编程》这本书只有两百多页,却花了一章的内容去阐述这个问题,足以看出这个问题的重要性,要想透彻理解C语言的声明问题仅仅看书是远远不够的,需要平时多实践并大量阅读别人写的代码。下面借鉴《C专家编程》书中的两个
C语言文件操作解析(一)在讨论C语言文件操作之前,先了解一下与文件相关的东西。一.文本文件和二进制文件 文本文件的定义:由若干行字符构成的计算机文件,存在于计算机系统中。文本文件只能存储文件中的有效字符信息,不能存储图像、声音等信息。狭义上的二进制文件则指除开文本文件之外的文件,如图片、DOC文档。
C语言文件操作解析(三) 在前面已经讨论了文件打开操作,下面说一下文件的读写操作。文件的读写操作主要有4种,字符读写、字符串读写、块读写以及格式化读写。一.字符读写 字符读写主要使用两个函数fputc和fgetc,两个函数的原型是: int fputc(int ch,FILE *fp);若写入成功则
浅谈C语言中的位段 位段(bit-field)是以位为单位来定义结构体(或联合体)中的成员变量所占的空间。含有位段的结构体(联合体)称为位段结构。采用位段结构既能够节省空间,又方便于操作。 位段的定义格式为: type [var]:digits 其中type只能为int,unsigned int,s
C语言文件操作解析(五)之EOF解析 在C语言中,有个符号大家都应该很熟悉,那就是EOF(End of File),即文件结束符。但是很多时候对这个理解并不是很清楚,导致在写代码的时候经常出错,特别是在判断文件是否到达文件末尾时,常常出错。1.EOF是什么? 在VC中查看EOF的定义可知: #def
关于VC+ʶ.0中getline函数的一个bug 最近在调试程序时,发现getline函数在VC+ʶ.0和其他编译器上运行结果不一样,比如有如下这段程序:#include &lt;iostream&gt;#include &lt;string&gt;using namespace std;int
C/C++浮点数在内存中的存储方式 任何数据在内存中都是以二进制的形式存储的,例如一个short型数据1156,其二进制表示形式为00000100 10000100。则在Intel CPU架构的系统中,存放方式为 10000100(低地址单元) 00000100(高地址单元),因为Intel CPU
浅析C/C++中的switch/case陷阱 先看下面一段代码: 文件main.cpp#includeusing namespace std;int main(int argc, char *argv[]){ int a =0; switch(a) { case ...
浅谈C/C++中的typedef和#define 在C/C++中,我们平时写程序可能经常会用到typedef关键字和#define宏定义命令,在某些情况下使用它们会达到相同的效果,但是它们是有实质性的区别,一个是C/C++的关键字,一个是C/C++的宏定义命令,typedef用来为一个已有的数据类型
看下面一道面试题:#include&lt;stdio.h&gt;#include&lt;stdlib.h&gt;int main(void) { int a[5]={1,2,3,4,5}; int *ptr=(int *)(&amp;aʱ); printf(&quot;%d,%d&quot;,*(
联合体union 当多个数据需要共享内存或者多个数据每次只取其一时,可以利用联合体(union)。在C Programming Language 一书中对于联合体是这么描述的: 1)联合体是一个结构; 2)它的所有成员相对于基地址的偏移量都为0; 3)此结构空间要大到足够容纳最&quot;宽&quo
从一个程序的Bug解析C语言的类型转换 先看下面一段程序,这段程序摘自《C 专家编程》:#include&lt;stdio.h&gt;int array[]={23,34,12,17,204,99,16};#define TOTAL_ELEMENTS (sizeof(array)/sizeof(ar
大端和小端 嵌入式开发者应该对大端和小端很熟悉。在内存单元中数据是以字节为存储单位的,对于多字节数据,在小端模式中,低字节数据存放在低地址单元,而在大端模式中,低字节数据存放在高地址单元。比如一个定义一个short型的变量a,赋值为1,由于short型数据占2字节。在小端模式中,其存放方式为0X40
位运算和sizeof运算符 C语言中提供了一些运算符可以直接操作整数的位,称为位运算,因此位运算中的操作数都必须是整型的。位运算的效率是比较高的,而且位运算运用好的话会达到意想不到的效果。位运算主要有6种:与(&amp;),或(|),取反(~),异或(^),左移(&gt;)。1.位运算中的类型转换位
C语言文件操作解析(四)在文件操作中除了打开操作以及读写操作,还有几种比较常见的操作。下面介绍一下这些操作中涉及到的函数。一.移动位置指针的函数 rewind函数和fseek函数,这两个函数的原型是:void rewind(FILE *fp); 将位置指针移动到文件首 int fseek(FILE
结构体字节对齐 在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题。从理论上讲,对于任何变量的访问都可以从任何地址开始访问,但是事实上不是如此,实际上访问特定类型的变量只能在特定的地址访问,这就需要各个变量在空间上按一定的规则排
C语言文件操作解析(二)C语言中对文件进行操作必须首先打开文件,打开文件主要涉及到fopen函数。fopen函数的原型为 FILE* fopen(const char *path,const char *mode) 其中path为文件路径,mode为打开方式 1)对于文件路径,只需注意若未明确给出绝