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

数据类型和变量

数据类型:固定内存大小的别名(本质)
变量
  • 一段实际连续存储空间的别名

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

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

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,1
2,2
4,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.000000000000001
float 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的使用受系统大小端的影响

这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值