国嵌C语言 · 笔记 1:关键字

来源:互联网 发布:机甲mesuit 知乎 编辑:程序博客网 时间:2024/06/08 16:12

数据类型和变量

数据类型:固定内存大小的别名(本质)

变量

  • 一段实际连续存储空间的别名

  • 程序中通过变量来申请并命名存储空间

  • 通过变量的名字可以使用存储空间

eg:

int i;//告诉编译器需要4个字节大小的内存,并把这段内存命名为i,编译器就会分配一段内存空间。
#include <stdio.h>int main(){    char c = 0;    short s = 0;    int i = 0;//数据类型:固定内存的别名 //char :1个字节的别名 //short:2个字节的别名 //int  :4个字节的别名 //sizeof(char):去查找char是几个字节的别名     printf("%d, %d\n", sizeof(char), sizeof(c));     printf("%d, %d\n", sizeof(short), sizeof(s));    printf("%d, %d\n", sizeof(int), sizeof(i));    return 0;}
运行结果:1,12,24,4
#include<stdio.h>typedef int INT;typedef unsigned char BYTE ;typedef struct _demo(     short a;     BYTE b1;     BYTE b2;     INT 3;)DEMO:int main(){    INT32 i32;    BYTE byte;    DEMO d;    printf("%d,%d\n",sizeof(INT32),sizeof(i32));    printf("%d,%d\n",sizeof(BYTE),sizeof(byte));    printf("%d,%d\n",sizeof(DEMO),sizeof(d));    return 0;}

auto、register、static关键字

auto:

  • c语言中局部变量的默认属性

  • 编译器默认所有局部变量都是auto类型的

register:

  • 指明变量存储于寄存器中(访问速度快)(局部)

  • 没有地址可以访问到(C语言规定:地址是内存中的空间

static:

  • 静态变量(只被初始化一次)

  • 在程序的静态区分配空间

  • 文件作用域限定符:限定在所定义此变量函数的文件中使用(static所定义的全局变量,函数),只有从一个文件访问static变量、static函数。

auto:变量存储于程序的栈中,默认属性
static:变量存储在程序静态去中
register:变量请求存储器CPU寄存器中(适用于实时系统中

if、switch、do-while、while、for关键字

分支语句:

if

  • else匹配之前离他最近的if语句

if语句中零值比较注意点

  • bool型变量应直接出现于条件中,不要直接进行比较
    C语言中用0表示假,非零表示真不能想当然认为bool变量1就是真!!!

  • 普通变量和 零 值 比较,0放左边,避免手误导致bug(难找)

  • float型的变量不能直接进行0值比较,需要定义精度
#define EPSINON   0.000000000000001float f = 5.0;if((5-EPSINON<=f)&&(f<=5+EPSINON))    {         **********;    }

switch

  • case语句中的值只能是整形或字符型

case语句排列顺序分析

  • 按字母或数字顺序排雷各条语句
  • 正常情况放前面,异常置后
  • default语句只用于真正的默认情况

if :适用于范围分支结构(程序清晰,可读性强)

switch:各个离散值判断(简洁,可读性强)

循环语句

  • 通过条件表达式判定是否执行循环体
  • 条件表达式遵循if语句表达式的原则

do:先执行,后判断。循环体至少执行一次。

while:先判断,后执行。循环体可能不执行。

for:先判断,后执行 。比while简洁,可读性高。

break:终止循环(跳出一个块{ })

continue:终止本次循环,进入下一次循环

5.const和volatile

const修饰变量

  • 在C语言中const修饰的变量是只读的,其本质还是变量

  • const修饰的变量会在内存占用空间

  • 本质上const只对编译器有用,在运行时无用
const int a = 1;

左值:报错
右值:
1.int b = a;

2.int *p=(int *) & a ;//(取地址符,到内存里面取值)

int main(){    const int a = 1int *p = (int*)&a;//    printf("%d\n",a);//到内存取值    *p = 3;//利用指针改变内存中a的值    printf("%d\n",a);}

const修饰数组

  • 在C语言中const修饰的数组是只读的

  • const修饰的数组空间不可被改变(针对现代c编译器,不是所有c编译器都这样)
const int A[5] = {1,2,3};int* p = (int*)A;int i = 0;for(i=0,i<5,i++){    p[i]=5-i;//ERROR}

const修饰指针

  • const int* p; //p指向的地址可变,p指向的内容不可变
  • int const* p; //p指向的地址可变,p指向的内容不可变
  • int* const p; //p指向的地址不可变,p指向的内容可变
  • const int* const p; //p和p指向的内容都不可变

    口诀:左数右指
    有*的时候
    以*为界,左边数(指针指向的内容)不可改变,右边指针指向的地址不可改变

  • 当const出现在*号左边时指针指向的数据为常量
  • 当const出现在*后右边时指针本身为常量
int main(){   int i =0;   const int* const p = &i;   *p = 3;//不可改变指针指向地址的内容const int*(左数)   p = NULL;//不可改变指针int* const p(右指)   return 0;}

const修饰函数参数和返回值

  • const修饰函数参数表示在函数体内不希望改变参数的值

  • const修饰函数返回值表示返回值不可改变,多用于返回指针的情形

const int* fun()//函数返回const 类型的指针{    static int count = 0;    count ++;    return &count;}int main(){    int i = 0;    const int * p = fun();//指针类型要和接收的类型一样    printf("%d\n",*p);}

volatile

  • volatile可理解为“编译器警告指示字”

  • volatile用于告诉编译器必须每次去内存中取变量值

  • volatile主要修饰可能被多个线程访问的变量

  • volatile也可以修饰可能被未知因数更改的变量

int obj = 10;int a = 0;int b = 0;a= obj;sleep(100);b=obj;//编译器在编译的时候发现obj没有被当成左值使用,因此会“聪明”的直接将obj替换成10,而把a和b都赋值为10。//此时加上vilatile int obj = 10;//要求编译器每次从内存中取obj的值
问题:
const和volatile是否可以同时修饰一个变量?
const volatile int i = 0; 这个时候i具有什么属性?编译器如何处理这个变量?

6.struct和union分析

空结构体占多少内存?

struct D{};int main(){    struct D d1;    struct D d2;    printf("%d\n",sizeof(struct D));    printf("%d,%0x\n",sizeof(d1),&d1);    printf("%d,%0x\n",sizeof(d2),&d2);    return 0;}取地址:  %p  或者  %0x(以16进制数显示)

灰色地带,空结构体占一个字节大小的内存,

由结构体产生柔性数组

  • 柔性数组即数组大小待定的数组

  • C语言中结构体的最后一个元素可以是大小未知的数组

  • C语言中可以由结构体产生柔性数组
#include <stdio.h>#include <malloc.h>typedef struct _soft_array{    int len;    int array[];}SoftArray;int main(){      int i = 0;    SoftArray* sa = (SoftArray*)malloc(sizeof(SoftArray) + sizeof(int) * 10);    sa->len = 10;    for(i=0; i<sa->len; i++)    {        sa->array[i] = i + 1;    }    for(i=0; i<sa->len; i++)    {        printf("%d\n", sa->array[i]);       }    free(sa);    return 0;}

union和struct的区别

  • struct中的每个域在内存中都独立分配空间
  • union只分配最大域的空间,所有域共享这个空间

union使用注意事项

union的使用受系统大小端的影响

这里写图片描述