C语言复习第三天

enum,sizeof,typedef 分析

enum类型的使用方法

1、enum是C语言中的一种自定义类型
2、enum值是可以根据需要自定义的整型值
3、第一个定义的enum值默认是 0
4、默认情况下的enum值是在前一个定义值的基础上加1
5、enum类型的变量只能取定义时的离散值
#include <stdio.h>
enum color
{
  red,
  green=2,
  blue,
  black
};
int main()
{
  enum color c = blue;
  printf(" c is %d\n",c);
  return 0;
}

enum类型的特殊意义

1、enum中定义的值是C语言中真正意义上的常量
2、在工程中enum多用于定义整形常量

enum使用实例

#include <stdio.h>

enum   //无名枚举,用于定义常量
{
    ARRAY_SIZE = 10
};
enum Color
{
    RED    = 0x00FF0000,
    GREEN  = 0x0000FF00,
    BLUE   = 0x000000FF
};
void PrintColor(enum Color c)
{
    switch( c )
    {
        case RED:
            printf("Color: RED (0x%08X)\n", c);
            break;
        case GREEN:
            printf("Color: GREEN (0x%08X)\n", c);
            break;
        case BLUE:
            printf("Color: BLUE(0x%08X)\n", c);
            break;
    }
}
void InitArray(int array[])
{
    int i = 0;
    
    for(i=0; i<ARRAY_SIZE; i++)
    {
        array[i] = i + 1;
    }
}
void PrintArray(int array[])
{
    int i = 0;
    
    for(i=0; i<ARRAY_SIZE; i++)
    {
        printf("%d\n", array[i]);
    }
}
int main()
{
    enum Color c = GREEN;
    
    int array[ARRAY_SIZE] = {0};
    
    PrintColor(c);
    
    InitArray(array);
    
    PrintArray(array);
    
    return 0;
}

sizeof 分析

1、sizeof是C语言内置关键字而不是函数,相当于宏
 ——在编译过程中所有的sizeof将被具体的值所替代
 ——程序执行的过程与sizeof没有任何关系
int f()
{
    printf("Delphi Tang\n");   
    return 0;
}
int main()
{
    int var = 0;    
    int size = sizeof(var++);    
    printf("var = %d, size = %d\n", var, size);    
    size = sizeof(f());    
    printf("size = %d\n", size);   
    return 0;
}

结果:
var++,func函数并没有执行并没有执行,因为在编译过程中sizeof已经被具体的值替代。
在这里插入图片描述

typedef 分析

1、typedef 用于给一个已经存在的数据类型重命名
2、typedef 本质上不能产生新的类型
3、typedef 重命名的类型:
	——可以在typedef 语句之后定义
	——不能被unsigned和signed修饰

用法: typedef type new_name;
使用示列

#include <stdio.h>
typedef int Int32;
struct _tag_point
{
    int x;
    int y;
};
typedef struct _tag_point Point;
typedef struct
{
    int length;
    int array[];
} SoftArray; 
typedef struct _tag_list_node ListNode;
struct _tag_list_node
{
    ListNode* next;
};
int main()
{
    Int32 i = -100;        // int 
    //unsigned Int32 ii = 0;
    Point p;               // struct _tag_point
    SoftArray* sa = NULL;   
    ListNode* node = NULL; // struct _tag_list_node*
    return 0;
}

注释符号

1、注释应该准确易懂,防止 二义性
2、注释是对代码的提示,避免臃肿和喧宾夺主
3、注释用于阐述原因和意图而不是描述程序的运行过程

tips

注释在预编译期间会被当成空格。

#include <stdio.h>
int main()
{
    int/*...*/i;
    char* s = "abcdefgh      //hijklmn"; 
    //Is it a \
    valid comment?    
    in/*...*/t i;    
    return 0;
}

预处理命令:gcc -E -o tt.i tt.c

在这里插入图片描述

接续符和转义符

接续符

1、C语言中的接续符(\)是指示编译器行为的利器
2、编译器会将反斜杠剔除,跟在反斜杠后面的字符自动接续到前一行
3、在接续单词时,反斜杠之后不能有空格,反斜杠的下一行之前也不能有空格
4、接续符适合在定义宏代码块时使用
#in\
clud\
e <st\
dio.h>

in\
t m\
ain(\
)
{
pri\
ntf\
    (\
    "Hello D.T.\n"
    )\
    ;
    
ret\
urn 0;
}

预编译后的结果
在这里插入图片描述

接续符的应用

定义宏定义模块:

#define SWAP(a,b)\
{                \
    int temp=a;  \
    a=b;         \
    b=temp;      \
}

int main()
{
    int a = 1;
    int b = 2;
    int c = 3;    
    SWAP(a,b);    
    printf("a = %d, b = %d\n", a, b);    
    SWAP(b,c);   
    printf("b = %d, c = %d\n", b, c);  
    return 0;
}

tips
宏定义的本质就是替换
预处理后的代码:
在这里插入图片描述
结果:
在这里插入图片描述

转义符

1、C语言的转义符(\)主要用于表示无回显字符,也可以用于表示常规字符
2、当分斜杠(\n)作为作为转义符使用时必须出现在单引号或者双引号之间。

在这里插入图片描述

#include <stdio.h>
int main()
{
    char enter = '\n';  
    char* p = "\141\t\x62";
    printf("%s", p);
    printf("%c", enter);  
    return 0;
}

单引号和双引号

1、C语言中的单引号用来表示字符字面量
	’a‘表示字符字面量
	在内存中占一个字节
	'a'+1表示'a'的ASCII码加1,结果为'b'
2、C语言中的双引号用来表示字符串字面量
	"a"表示字符串字面量
	在内存占两个字节
	“a”+1表示指针运算,结果指向"a"结束符’\0‘

实例:

tips
1、字符字面量被编译程对应的ASCII码
2、字符串字面量被编译为对应的内存地址
3、printf的第一个参数被当成字符串字面量内存地址
4、内存的低地址空间不能在程序中随意访问

#include <stdio.h>
int main()
{
     char* p1 =  1 ;
     char* p2 = '1';
     char* p3 = "1";
    printf("p1 adress is 0x%x\n",p1);   //p1指针指向的地址
    printf("p2 adress is 0x%x\n",p2);   //p2指针指向的地址  0x31为字符1的ASCII码值
    printf("p3 adress is 0x%x\n",p3);  //p3指针指向的地址
    
    printf("p3 value is  %s\n",p3);     //访问p3地址  p2,p1地址访问会出段错误
    //printf('\n')  出错
    printf("\n");
    
    return 0;
}

在这里插入图片描述在这里插入图片描述在这里插入图片描述

tips
这段代码发生了什么?

char C="string"

分析:
1、编译后字符串"string"的内存地址被赋值给变量c
2、内存地址占用4个字节,而变量c只占用1个字节
3、由于类型不同,赋值后产生截断

小结

1、单引号括起来的单个字符代表整数
2、双引号括起来字符代表指针
3、C编译器接受字符和字符串的比较,无意义
4、C编译器允许字符串对字符变量赋值,只能得到错误结果

逻辑运算符分析

1、逻辑运算符
 && ,   ||    ,        !

示列:

#include <stdio.h>

int main()
{
    int i = 0;
    int j = 0;
    int k = 0;
    ++i || ++j && ++k;
    printf("%d\n", i);
    printf("%d\n", j);
    printf("%d\n", k);
    
    return 0;
}

结果?
1 0 0

程序中的短路

-||从左往右开始计算:
	当遇到真的条件是停止计算,整个表达式为真
	所有条件为假时表达式才为假
	
-&& 从左往右开始计算:
	当遇到假的条件是停止计算,整个表达式为假
	所有条件为真时表达式才为真

示列程序分析:

tips
在这里插入图片描述

! 分析

C语言中的逻辑非"!"只认得0,只有0返回1 ,其余全返回0

位运算符分析

     1、位运算符直接对bit位进行操作,其效率最高

在这里插入图片描述

左移和右移的注意点

1、左操作数必须为整数类型
		char 和 short 被隐式转换为int 进行移位操作
2、右操作数的范围必须为:【0,31】
3、左移运算符<<将运算数的二进制位左移
     规则 :高位丢弃,低位补0
4、右移运算符<<将运算数的二进制位右移
     规则 :高位补符号位,低位丢弃。

示列:
tips
-1再怎么右移始终是-1

#include <stdio.h>
int main()
{
    printf("%d\n", 3 << 2); 
    printf("%d\n", 3 >> 3); 
    printf("%d\n", -1 >> 2);    //-1再怎么右移始终是-1
    printf("%d\n", 0x01 << 2 + 3);   //运算符的优先级
    printf("%d\n", 3 << -1); // oops!    
    return 0;
}

在这里插入图片描述

实例:交换两个整形变量的值(三种方法):

#include <stdio.h>
#define SWAP(a,b)\
{                \
  int temp=a;    \
  a=b;           \
  b=temp;        \
}
#define SWAP1(a,b)\
{                 \
   a=a+b;         \
   b=a-b;         \
   a=a-b;         \
}
#define SWAP2(a,b)\
{                 \
  a=a^b;          \
  b=a^b;          \
  a=a^b;          \
}
int main()
{
   int i=-3;
   int j=9;
   printf("i=%d ,j=%d\n",i,j);
   SWAP2(i,j);
   printf("i=%d ,j=%d\n",i,j);   
   return 0;
}

小结

1、位运算符只能用于整数类型
2、左右移位运算符的右操作数必须位【0,31】
	——在gcc编译器上超过 位数,该段程序不会执行
3、位运算没有短路规则,所有操作数均会求值
4、位运算效率最高
5、运算优先级:
	——四则运算 > 位运算 > 逻辑运算
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值