什么是常量、变量和数据类型?

二、常量、变量和数据类型

  • 关键字(Keyword)

    又称为保留字,C语言中预先预定的具有固定含义的一些单词(if,while,...) 由ANSI标准定义的C语言关键字共32个。

  • 标识符(Identifier)

    系统预定义标识符

    用户自定义标识符

  • 运算符(Operator)

    34种(+,-,*,...)

  • 分隔符(Separator)

    空格、回车/换行、逗号等

  • 其他符号

    大花括号“{”和“}”通常用于标识函数体或者一个语句块“/”和“/”是程序注释所需的定界符

b,B,KB,MB,GB,TB

  • 一个字节有点多大?

    • 可以表示数字0~255

    • 保存一个字符(英文字母、数字、符号),ASCII编码

    • 两个字节保存一个汉字

      • GB2312,6763字

      • GB13000.120920字

      • GB18030,27533字

      • BIG5,13000字

    • 两个字节保存一个宽字符,UNICODE编码

      • 65536个字符

1.大小

  • bit,中文叫法:位

  • Byte,中文叫法:字节

  • Kilobyte(KB),中文叫法:K

  • Megabyte(MB),中文叫法:兆

  • Gigabite(GB),中文叫法:G

  • Terabyte(TB),中文叫法:T

  • GB2312,6763字

    • GB13000.120920字

    • GB18030,27533字

    • BIG5,13000字

1TB==1024GB 1GB==1024MB 1MB==1024KB 1KB==1024B 1B==8b

2.数据类型

程序体现:

#include<stdio.h>

int main()
{
    printf("%lu\n",sizeof(char));       //1 0~2 8 -1
    printf("%lu\n",sizeof(short));      //2 0~2 16 -1
    printf("%lu\n",sizeof(int));        //4 0~2 32 -1
    printf("%lu\n",sizeof(long));       //4 
    printf("%lu\n",sizeof(long long));  //8 0~2 64 -1
    
    return 0;
}

浮点数的精度和范围 

1)浮点数的陷阱
#include<stdio.h>

int main()
{
    float f;
    f = 123.456;
    
    if(f == 123.456)
    {
        printf("f确实等于123.456");
    }else
    {
        printf("实际上,f等于%f\n",f);
    }
    
    return 0;
    
}

//实际上,f等于%f\n   123.456001

3.ASCII码表

1)正确的输入得到正确的结果
#include <stdio.h>
#include <stdlib.h>

int my_atoi(char *str)
{
    int total = 0;
    
    while (*str == ' ')
    {
        str++;
    }
    
    if (*str == '-')
    {
        flag = -1;
    }else if(*str == '+')
    {
        str++;
    }
    
    //迭代
    while (*str >= '0' && *str <= '9')
    {
        total = total * 10 + (*str - '0');
        str++;
    }
    
    return total;
}

int main()
{
    char str[5] = "       -12345";   //"    --12312qad123" 程序的局限
    int total = 0;
    //total = (str[0] - '0') * 100 + (str [1] - '0') * 10 + (str[2] - '0') * 1;
    total = my_ayoi(str);
    printf("%d\n",total);
    
    return 0;
}
2)小写字母转换为大写字母
#include<stdio.h>
​
int main()
{
    char c = 'a'
    c = c - ('a' - 'A');
    printf("%c\n", c);
    
    return 0;
}
#include<stdio.h>
​
void upper(char *str != '\0')
{
    if(*str <= 'z' && *str >= 'a')
    {
        *str = *str - ('a' - 'A')
    }
    
    str++;
}
​
int main()
{
    //char *str = "Helloworld, I love China!";  / 存于ROdata段,不可修改。段错误
   
   
    //数组 str[]在栈空间可修改 / "  "ROdata段   "  "需要多少[]取多少
    char str[] = "Helloworld, I love China!";
    
    return 0;
}

const关键字

  • 用const修饰定义的变量为常量 ?    const int i = 0;

  • const变量只能在定义时赋值,然后不能在改变其值。

4.类型转换

两个栓数类型的操作数做算数运算,比如a+b,如果两边操作数的类型不同,编译器会自动做类型转换,是两边类型相同之后才做运算。

如果又一遍的类型是 long double,则把另一边也转换成long double。

否则,如果有一边的类型是double,则把另一边也转成double。

否则,如果有一边的类型是float,则把另一边也转成float。

否则,两边应该是整形,对a和b做Intger Promotion。

  • 混合运算

    • 当操作数1和操作数2的类型不同时,即为混合运算。

    • 当运算时要求类型应相同。即先转换,在运算,

1)赋值类型转换

#include <stdio,h>
​
int main()
{
    char a;
    unsigned int b;
    a = 255;
    b = a;
    
    printf("%d\n",a);  //- 1
    printf("%u\n",b);  // -1 
    
    return 0;
}

无符号数和有符号数不能混着用。

若果赋值或初始化时等号两边的类型不同,则编译器会把等号右边的类型转换成等号左边的类型在做赋值。

2)强制类型转换

#include <stdio.h>
int main()
{
    printf("%lf\n",(double)(3/4));
    
    return 0;
}
  • 强制类型转换给C语言编程带来了极大地灵活性,也正是这种灵活性,也埋下了无数的隐患

  • 当目的结构的空间大于源结构的空间时,要重点关注内存访问超过源结构范围的情形,可能越界

  • 当目的结构空间小于源结构的空间时,要重点关注对目的的结构赋值不能完全覆盖源结构范围的情形,可能遗漏

  • 与结构体之间的强制类型转化相比,基本数据结构的强制类型转换更同意出现上面描述的情况,使用的时候,一定要慎之又慎

5.变量

  • 字母开头,后跟字母,数字和下划线组成。

  • C语言中的关键字不能作为变量名

    • 注意:变脸必须先定义或声明后使用;

    • 变量中存放的只能是数据,而且只能是一个数据,往变量中存放数据的操作称为赋值

#include <stdio.h>
​
int main()
{
    int a = 100;
    
}

1.定义和声明

声明可以声明很多次,定义只能定义一次。定义为变量分配地址和存储空间。

注意:

    - 变量必须先定义或声明后使用;
    - 变量中存放的只能是数据,而且只能是一个数据,往变量中存放数据的操作称为赋值。
    - 变量的“名”和变量的“值”不同,变量的“名”是该变量所代表的存储单元的标志,而变量的“值”是指存储单元中的内容。
//1.c
#include <stdio,h>
​
//声明
extern int g_a;
​
int main()
{
    extern int g_a;
    int total = 100;
    printf("%d\n",g_a);
    
    return 0;
}
​
声明一般放.h文件,放.c文件可能会重定义
//2.c
  int g_a = 250;
//int g_a = 250;
//重定义
​
//gcc 1.c 2.c -o main
//链接 gcc 1.0 2.0
​
//预编译 编译 汇编 + 链接

2.初始化和赋值

#include <stdio,h>
​
extern int g_a;
​
int main()
{
    //初始化,不能再赋值
    const int total = 0;
    //错误
    int total = 100;
    printf("%d\n",g_a);
    
    return 0;
}
#include <stdio.h>
​
int main()
{
    int a = 100;
    int b = 200;
    int total = 0;
    
    total = a + b;
    
    printf("%d\n",total);
    
    return 0;
}

3.变量的作用域

代码块作用域

全局作用域

文件作用域

原型作用域

函数作用域

  • 重定义

#include<stdio.h>
​
tin main()
{
    int a = 100;
    int b = 200;
    int a = 300;
    int b = 400;
    
    return 0;
}
  • 变量隐藏

#include<stdio.h>
​
tin main()
{       //1 3开始
    int a = 100;
    int b = 200;
    {   
        //1结束
        printf("1:%d %d\n",a,b);
        //2开始
        int a = 300;     //隐藏
        int b = 400;
        printf("2:%d %d\n",a,b);
    }   //2结束
    printf("3:%d %d\n",a,b);
    
    return 0;
}       //3结束
1)全局变量

全局变量定义在所有的函数体之外,它们在程序开始运行时分配存储空间,再程序结束时释放存储空间,再任何函数中都可以访问全局变量。

#include <stdio.h>
​
static int g_total = 0;
//加static,在本文件中可见
​
void fun()
{
    g_total++;
}
​
int main()
{
    printf("%d\n",g_total); //0
    fun();
    printf("%d\n",g_total); //1
    
    return 0;
}
​
/*
静态全局变量内部链接属性,在别的.c文件不可用
函数前也可以写
*/
2)局部变量

函数中定义的变量称为局部变量

局部变量的含义:

1.一个函数中定义的变量不能被另一个函数调用

2.每次调用函数时局部变量都表示不同的存储空间

#include <stdio.h>
void foo (void)
{
    int i;
    print("%d\n",i);
    i = 777;
}
​
int main(void)
{
    foo();
    print("hello\n");
    foo();
    return 0;
}

局部变量可以用类型相符的任意表达式来初始化,而全局变量只能用常量表达式(Constant Expression)初始化。

  • 链接属性

    • external(外部)

    • internal(内部)

    • none(无)

    static与extern

    加static是把外部链接属性改成内部连接属性

    如果具有外部链接属性加extern

4.存储类型

  • 变量的存储类型是指存储变量的内存类型

  • 主要包括 自动变量(auto) 静态变量(static) 寄存器变量(register)

#include <stdio.h>
#include <stdlib.h>
​
int countbit(unsigned int x)
{
    int total = 0;
    unsigned int mask = 1u;
​
    while (x > 0)
    {
       total += x & mask;
       x >>= 1;
    }
​
    return total;
}
​
void print_bin(unsigned int x)
{
    int i;
    unsigned int mask = 1u;
​
    for (i = sizeof(int)* 8 - 1; i >= 0; i--)
    {
        if ((mask << i) & x)
        {
            putchar('1');
        }else
        {
            putchar('0');
        }
​
        if (i % 4 == 0)
        {
            putchar(' ');
        }
    }
    putchar('\n');
}
​
unsigned int ror(unsigned int x, int n)
{
    int i;
​
    while (n < 0)
    {
        n = n + 32;
    }
    
    n = n % 32;
​
    for (i = 0; i < n; i++)
    {
        x = (x >> 1) + (x << 31);
    }
​
    return x;
}
​
unsigned int ror2(unsigned int x, int n)
{
    while (n < 0)
    {
        n = n + 32;
    }
    
    n = n % 32;
​
    return (x >> n) + (x << (32 - n));
}
​
int main()
{
    unsigned int x = 0xdeadbeef;//0xefdeadbe;
    print_bin(x);
    print_bin(ror(x, -18));
    print_bin(ror2(x, -18));
​
    return 0;
}

结构体存储

#include <stdio.h>
​
typedef struct date
{
    int year;
    int month;
    int day;
}date;
​
typedef struct  student
{
    int ID;
    char name[20];
    char sex;
    int age;
    date birthday;
}student;
​
void print_student(student *s)
{
    printf("%d %s %c %d ", s->ID, s->name, s->sex, s->age);
    printf(":%d-%d-%d\n", s->birthday.year, s->birthday.month,s->birthday.day);
}
​
int main()
{
    student s1 = {1,"Qizhen",'m',18, {2006, 1, 21}};
    student s2 = {2,"JiJiaxin",'f',17, {2007, 5, 20}};
​
    print_student(&s1);
    print_student(&s2);
​
    return 0;
}

5.变量的特性:

  • 变量的名

  • 变量的值

  • 变量的地址

  • 变量的类型

  • 变量的存储类型

  • 变量的作用域

  • 变量的生命周期

6.排序方式

1). 插入排序

  • 直接插入排序:将数组中的所有元素依次跟前面已经排好的元素相比较,如果选择的元素比已排序的元素小,则交换,直到全部元素都比较过。

  • 希尔排序:也称递减增量排序算法,是插入排序的一种更高效的改进版本。通过选定一个增量序列,将待排序记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。

2). 选择排序

  • 简单选择排序:从未排序的数组中选择最小的元素,将其放在已排序的数组的末尾。重复这个过程,直到所有元素都排序完毕。

  • 堆排序:利用堆这种数据结构所设计的一种排序算法。通过构建大顶堆(或小顶堆),不断取出堆顶元素(最大或最小),然后重新调整堆,直到所有元素都被取出。

3). 交换排序

  • 冒泡排序:重复地遍历要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。

  • 快速排序:通过选取一个“基准”元素,将数组分为两个子数组,一个包含所有小于基准的元素,另一个包含所有大于基准的元素。然后递归地对这两个子数组进行快速排序。

4). 归并排序

  • 归并排序:采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

5). 基数排序

  • 基数排序:按照低位先排序,然后收集;再按照高位排序,然后再收集;以此类推,直到最高位。基数排序是非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。

(1)冒泡排序
#include <stdio.h>
​
void print_array(int *v,int len)
{
    int i;
    
    for(i = 0;i < len; i++)
    {
        printf("%d",v[i]);
        printf("\n");
    }
}
​
void bubble_sort(int *v, int len)
{
    int i;
    int j;
    int tmp;
    
    for(i = 0;i < len - 1; i++)
    {
        for(j = 0; j < len - 1 - i;j++)
        {
        if (v[j+1] < v[j])
            {
            tmp = v[j];
            v[j] = v[j + 1];
            v[j + 1] = tmp;
            }
        }
    }
}
​
int main()
{
    int a[10] = {-1, -12, 13, 41, 15, 63, -7, 89, 91, -10};
    //一个个比较,交换;
    
    print_array(a, 10);
    bubble_sort(a, 10);
    print_array(a, 10);
    
    return 0;
}
(2)快速排序
#include <stdio.h>  
  
// 函数声明  
void quickSort(int arr[], int low, int high);  
int partition(int arr[], int low, int high);  
  
int main() {  
    int arr[] = {10, 7, 8, 9, 1, 5};  
    int n = sizeof(arr) / sizeof(arr[0]);  
    quickSort(arr, 0, n-1);  
    printf("Sorted array: \n");  
    for (int i = 0; i < n; i++)  
        printf("%d ", arr[i]);  
    printf("\n");  
    return 0;  
}  
  
// 快速排序函数  
void quickSort(int arr[], int low, int high) {  
    if (low < high) {  
        // pi 是分区后的索引,arr[pi] 现在在正确的位置  
        int pi = partition(arr, low, high);  
  
        // 递归地对左半部分进行快速排序  
        quickSort(arr, low, pi - 1);  
  
        // 递归地对右半部分进行快速排序  
        quickSort(arr, pi + 1, high);  
    }  
}  
  
// 分区函数  
int partition(int arr[], int low, int high) {  
    int pivot = arr[low];    // 选择第一个元素作为基准  
    int i = low - 1;  // 小于基准的元素的索引  
  
    for (int j = low; j <= high - 1; j++) {  
        // 如果当前元素小于或等于pivot  
        if (arr[j] <= pivot) {  
            i++;    // 增大小于pivot的元素的索引  
            // 交换arr[i]和arr[j]  
            int temp = arr[i];  
            arr[i] = arr[j];  
            arr[j] = temp;  
        }  
    }  
    // 交换arr[i+1]和arr[high](或pivot)  
    int temp = arr[i + 1];  
    arr[i + 1] = arr[high];  
    arr[high] = temp;  
  
    return (i + 1); // 返回基准的正确位置  
}
(3)选择排序
#include <stdio.h>  
  
// 函数声明  
void selectionSort(int arr[], int n);  
  
  
// 选择排序函数  
void selectionSort(int arr[], int n) 
{  
    int i, j, minIndex, temp;  
  
    // 移动未排序数组的边界  
    for (i = 0; i < n-1; i++) 
    {  
        // 寻找最小元素的索引  
        minIndex = i;  
        for (j = i+1; j < n; j++) 
        {  
            if (arr[j] < arr[minIndex]) 
            {  
                minIndex = j;  
            }  
        }  
  
        // 将找到的最小元素与未排序数组的第一个元素交换  
        temp = arr[minIndex];  
        arr[minIndex] = arr[i];  
        arr[i] = temp;  
    } 
}
​
int main() 
{  
    int arr[] = {64, 25, 12, 22, 11};  
    int n = sizeof(arr)/sizeof(arr[0]);  
  
    printf("原始数组: \n");  
    for (int i = 0; i < n; i++)  
        printf("%d ", arr[i]);  
    printf("\n");  
  
    selectionSort(arr, n);  
  
    printf("排序后的数组: \n");  
    for (int i = 0; i < n; i++)  
        printf("%d ", arr[i]);  
    printf("\n");  
  
    return 0;  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值