默染江山——c语言数据类型

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

一 概述

c语言有非常丰富的数据类型,整体上可分为四大类:基本数据类型、构造数据类型、指针类型和空类型。

这里写图片描述

二 基本数据类型

基本数据类型主要分为:整型、浮点型和字符类型。

1 整型
整形包括短整型、整形和长整形。

1.1短整形
short a=1;

1.2整形
一般占4个字节(32位),最高位代表符号,0表示正数,1表示负数,取值范围是-2147483648~2147483647,在内存中的存储顺序是地位在前、高位在后,例如0x12345678在内存中的存储如下:

  地址:0x0012ff78  0x0012ff79  0x0012ff7a  0x0012ff7b

  数据:  78      56        34      12

  定义:用int关键字,举例如下:

  int a=6;

1.3长整形
long a=10;

2 浮点型
浮点型包括单精度型和双精度型。

2.1单精度型

  浮点型,又称实型,也称单精度。一般占4个字节(32位),

  float a=4.5;

  地址:0x0012ff78  0x0012ff79  0x0012ff7a  0x0012ff7b

  数据:  00      00        90      40

2.2双精度型

  一般占8个字节(64位)

  double a=4.5;

  地址:0x0012ff78  0x0012ff79  0x0012ff7a  0x0012ff7b  0x0012ff7c  0x0012ff7d  0x0012ff7e  0x0012ff7f

  数据:  00      00        00      00      00        00      12      40

3 字符类型

  在各种不同系统中,字符类型都占一个字节(8位)。定义如下:

  char c=’a’;

  也可以用字符对应的ASCII码赋值,如下:

  char c=97;

三 构造类型

构造类型主要分为四种类型:数组、结构体、共用体和枚举。
1 数组
1.1定义:数组是由相同基本类型若干个元素组织在一起数据,它们有先后顺序,也可以按这个顺序对这些元素访问。
如int a[10],共有10个元素,每个元素的类型都相同,都为整型。
这10 个元素,按顺序分别是a[0]、a[1]、a[2]、a[3]、a[4]、a[5]、a[6]、a[7]、a[8]、a[9]。

1.2存储空间的划分:内存的分配是从高地址到低地址进行的,但一个数组内部元素又是从低到高进行的。

1.3二维数组是一个特殊的一维数组:它的元素是一维数组。例如int a[2][3]可以看作由一维数组a[0]和一维数组a[1]组成,这两个一维数组都包含了3个int类型的元素
这里写图片描述

1.4数组的应用

#include <stdio.h>

int main()
{
    // 使用注意
    // 都是正确写法
    //int ages[5] = {10 , 11, 12, 67, 56};
    //int ages[5] = {10, 11};
    //int ages[5] = {[3] = 10, [4] = 11};
    //int ages[] = {10, 11, 14};

    // 错误写法
    // int ages[];

    // 错误写法
    /* 只能在定义数组的同时进行初始化
    int ages[5];
    ages = {10, 11, 12, 14};
    */

    // 正确写法
    // int ages['A'-50] = {10, 11, 12, 14, 16};
    //int size = sizeof(ages);
    //printf("%d\n", size);

    // 正确写法
    /*
    int count = 5;
    int ages[count];
    ages[0] = 10;
    ages[1] = 11;
    ages[2] = 18;
    */

    //printf();
    // 错误写法
    // 如果想再定义数组的同事进行初始化,数组元素个数必须是常量,或者不写
    //int ages[count] = {10, 11, 12};


    int ages[] = {10, 11, 12, 78};

    // 计算数组元素的个数
    int count = sizeof(ages)/sizeof(int);

    for (int i = 0; i<count; i++)
    {
        printf("ages[%d]=%d\n", i, ages[i]);
    }

    return 0;
}

// 数组的基本使用
void arrayUse()
{
    // 数组的定义格式: 类型 数组名[元素个数];
    int ages[5] = {19, 29, 28, 27, 26};
    // 19 19 28 27 26]
    ages[1] = 29;

    /*
     ages[0] = 19;
     ages[1] = 19;
     ages[2] = 28;
     ages[3] = 27;
     ages[4] = 26;
     */

    /*
     遍历:按顺序查看数组的每一个元素
     */
    for (int i = 0; i<5; i++)
    {
        printf("ages[%d]=%d\n", i, ages[i]);
    }
}

2 结构体
数组中存储的是一系列相同的数据类型,那么如果想让一个变量存储不同的数据类型就要使用结构体。结构体是一种类型,并非一个变量,只是这种类型可以由其他C语言基本类型共同组成。

2.1可以在定义结构体类型的同时声明结构体变量;

2.2如果定义结构体类型的同时声明结构体变量,此时结构体名称可以省略;

2.3定义结构体类型并不会分配内存,在定义结构体变量的时候才进行内存分配;

2.4结构体类型的所占用内存大小等于所有成员占用内存大小之和。

具体分析请看以下代码:

#include <stdio.h>

//结构体类型Date
struct Date{
    int year;
    int month;
    int day;
};

struct Person{
    char *name;
    int age;
    struct Date birthday;//一个结构体中使用了另一个结构体类型,结构体类型变量声明前必须加上struct关键字
    float height;
};

int main(int argc, const char * argv[]) {
    struct Person p={"Wuxl",28,{1986,8,8},1.72};
    //定义结构体变量并初始化,不允许先定义再直接初始化,例如:struct Person p;p={"Wuxl",28,{1986,8,8},1.72};是错误的,但是可以分别赋值,例如p.name="Kenshin"

    printf("name=%s,age=%d,birthday=%d-%d-%d,height=%.2f\n",p.name,p.age,p.birthday.year,p.birthday.month,p.birthday.day,p.height); 
    //结果:name=Wuxl,age=28,birthday=1986-8-8,height=1.72,结构体的引用是通过"结构体变量.成员名称"(注意和结构体指针访问结构体成员变量区分,结构体指针使用p->a的形式访问)

    printf("len(Date)=%lu,len(Person)=%lu\n",sizeof(struct Date),sizeof(struct Person)); 
    //结果:len(Date)=12,len(Person)=32

    return 0;
}

3 枚举
枚举类型是比较简单的一种数据类型,事实上在C语言中枚举类型是作为整形常量进行处理的,通常称为“枚举常量”。


#include <stdio.h>

enum Season{ //默认情况下spring=0,summer=1,autumn=2,winter=3
    spring,
    summer,
    autumn,
    winter
};

int main(int argc, const char * argv[]) {
    enum Season season=summer; //枚举赋值,等价于season=1
    printf("summer=%d\n",season); //结果:summer=1

    for(season=spring;season<=winter;++season){
        printf("element value=%d\n",season);
    }
    /*结果:
     element value=0
     element value=1
     element value=2
     element value=3
     */
    return 0;
}

需要注意的是枚举成员默认值从0开始,如果给其中一个成员赋值,其它后面的成员将依次赋值,例如上面如果summer手动指定为3,则autumn=4,winter=5,而spring还是0。

4 共用体
共用体又叫联合,和结构体不同的是共用体所有成员共用一块内存,顺序从低地址开始存放,一次只能使用其中一个成员,union最终大小由共用体中最大的成员决定,对某一成员赋值可能会覆盖另一个成员。

#include <stdio.h>

union Type{
    char a;
    short int b;
    int c;
};

int main(int argc, const char * argv[]) {
    union Type t;
    t.a='a';
    t.b=10;
    t.c=65796;

    printf("address(Type)=%x,address(t.a)=%x,address(t.b)=%x,address(t.c)=%x\n",&t,&t.a,&t.b,&t.c);
    //结果:address(Type)=5fbff7b8,address(t.a)=5fbff7b8,address(t.b)=5fbff7b8,address(t.c)=5fbff7b8

    printf("len(Type)=%d\n",sizeof(union Type));
    //结果:len(Type)=4

    printf("t.a=%d,t.b=%d,t.c=%d\n",t.a,t.b,t.c);
    //结果:t.a=4,t.b=260,t.c=65796

    return 0;
}

这里需要重点解释一个问题:为什么t.a、t.b、t.c输出结果分别是4、260、65796,当然t.c等于65796并不奇怪,但是t.a前面赋值为’a’不应该是97吗,而t.b不应该是10吗?其实如果弄清这个问题共用体的概念基本就清楚了。

根据前面提到的,共用体其实每次只能使用其中一个成员,对于上面的代码经过三次赋值最终使用的其实就是t.c,而通过上面的输出结果我们也确实看到c是有效的。共用体有一个特点就是它的成员存储在同一块内存区域,这块区域的大小需要根据它的成员中长度最大的成员长度而定。由于上面的代码是在64位编译器下编译的,具体长度:char=1,short int=2,int=4,所以得出结论,Type的长度为4,又根据上面输出的地址,可以得到下面的存储信息(注意数据的存储方式:高地址存储高位,低地址存储地位):

这里写图片描述

当读取c的时候,它的二进制是“00000000 00000001 00000001 00000100”,换算成十进制就是65796;而经过三次赋值后,此时b的存储就已经被c成员的低位数据覆盖,b的长度是二,所以从起始地址取两个字节得到的二进制数据此时是“00000001 00000100”(b原来的数据已经被c低2位数据覆盖,其实此时就是c的低2位数据),换算成十进制就是260;类似的a此时的数据就是c的低一位数据”00000100”,换算成十进制就是4。

四 指针类型

通过指针访问变量称为间接访问, 简称间访。由于指针变量直接指向变量,所以称为单级间访。 而如果通过指向指针的指针变量来访问变量则构成了二级或多级间访。在C语言程序中,对间访的级数并未明确限制, 但是间访级数太多时不容易理解解,也容易出错,因此,一般很少超过二级间访。 指向指针的指针变量说明的一般形式为:
类型说明符** 指针变量名;
例1: int ** pp; 表示pp是一个指针变量,它指向另一个指针变量, 而这个指针变量指向一个整型量。下面举一个例子来说明这种关系。

main(){
    int x,*p,**pp;// 定义一个一级指针和一个二级指针。
    x=10;
    p=&x;// p指向存储变量x的内存地址。
    pp=&p;// pp指向存储指针p的内存地址。
    printf("x=%d\n",**pp); // 输出结果为10
} 

上例程序中p 是一个指针变量,指向整型量x;pp也是一个指针变量, 它指向指针变量p。通过pp变量访问x的写法是**pp。程序最后输出x的值为10。通过上例,读者可以学习指向指针的指针变量的说明和使用方法。

接下来我们看一下如何用二级指针访问访问指针数组的每一个元素。
例二:

main(){
static char *ps[]={ "BASIC","DBASE","C","FORTRAN",
"PASCAL"}; // 定义一个指针数组。
char **pps; // 定义一个二级指针。
int i;
for(i=0;i<5;i++){
pps=ps+i; // ps表示指向数组ps的第一个元素, ps+i表示依次指向ps数组的每一个元素。
printf("%s\n",*pps);// 依次输出pps指向的数组元素。
}
}

五 空类型(void)

有一类函数,调用后并不需要向调用者返回函数值,这种函数可以定义为“空类型”。其类型说明符为void。
例:

#include "stdio.h"
void fanhui()
{
    printf("返回为空!\n");
}

main()
{
    fanhui();// 此函数返回为空。
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值