第2天 C语言32个关键字

数据类型修饰符13个

short、int、long、char、float、double

			short :声明短整型变量或函数  
			int: 声明整型变量或函数 
			long :声明长整型变量或函数    
			float:声明浮点型变量或函数   
			double :声明双精度变量或函数  
			char :声明字符型变量或函数  
//获得基本数据类型的空间大小
#include <stdio.h>
int main()
{
	char character_type;
	short short_integer;
	int integer;
	long long_integer;
	float floating_point_type;
	double double_float;
	
	printf("character_type:%d\n",sizeof(character_type));
	printf("short_integer:%d\n",sizeof(short_integer));
	printf("integer:%d\n",sizeof(integer));
	printf("long_integer:%d\n",sizeof(long_integer));
	printf("floating_point_type:%d\n",sizeof(floating_point_type));
	printf("double_float:%d\n",sizeof(double_float));
	
}


unsigned与signed

unsigned:声明无符号类型变量或函数  
signed:声明有符号类型变量或函数  
无符号数只限于char int long short类型
float double类型没有无符号数
符号特指负号“-”

//获得无符号基本数据类型的空间大小
#include <stdio.h>
int main()
{
	unsigned char character_type;
	unsigned short short_integer;
	unsigned int integer;
	unsigned long long_integer;
	//unsigned float floating_point_type;
	//unsigned double double_float;
	
	printf("character_type:%d\n",sizeof(character_type));
	printf("short_integer:%d\n",sizeof(short_integer));
	printf("integer:%d\n",sizeof(integer));
	printf("long_integer:%d\n",sizeof(long_integer));
	//printf("floating_point_type:%d\n",sizeof(floating_point_type));
	//printf("double_float:%d\n",sizeof(double_float));
	
}

sizeof

计算数据类型长度,sizeof 是关键字不是函数
代码见上文

struct

用于声明结构体变量或函数;将一些相关联的数据打包成一个整体

#include <stdio.h>
int main()
{
		struct	student
	{
	}stu;
	printf("%d",sizeof(stu));
}
//sizeof(stu)的值是多少呢?

union

声明共用数据类型   
union 关键字的用法与 struct 的用法非常类似。
struct中的每个域在内存中都独立分配空间
union只分配最大域的空间,所有域共享这个空间

#include <stdio.h>
int main()
{

	union StateMachine
	{
		char character;
		int number; 
		char *str;
		//double exp;
	}stu;

	printf("%d\n", sizeof(stu));
}

enum

声明枚举类型
成员都是常量,也就是我们平时所说的枚举常量(常量一般用大写)。 enum 变量类型还可以给其中的常量符号赋值,如果不赋值则会从被赋初值的那个常量开始依次加 1,如果都没有赋值,它们的值从 0 开始依次递增 1。

#include <stdio.h> 
int main()
{
	enum Color
	{
		GREEN = 1, RED = 2, BLUE = 3, GREEN_RED = 10, GREEN_BLUE = 11
	}ColorVal;
	ColorVal = GREEN;
	printf("%d\n", sizeof(ColorVal));
	printf("%d\n", ColorVal);
}

typedef

为基本数据类型定义新的类型名
为自定义数据类型(结构体、共用体和枚举类型)定义简洁的类型名称
为数组定义简洁的类型名称
为指针定义简洁的名称

在实际使用中,typedef 的应用主要有如下4种。

1) 为基本数据类型定义新的类型名

也就是说,系统默认的所有基本类型都可以利用 typedef 关键字来重新定义类型名,示例代码如下所示:
typedef unsigned int COUNT;
而且,我们还可以使用这种方法来定义与平台无关的类型。比如,要定义一个叫 REAL 的浮点类型,在目标平台一上,让它表示最高精度的类型,即:
typedef long double REAL;
在不支持 long double 的平台二上,改为:
typedef double REAL;
甚至还可以在连 double 都不支持的平台三上,改为:
typedef float REAL;
这样,当跨平台移植程序时,我们只需要修改一下 typedef 的定义即可,而不用对其他源代码做任何修改。其实,标准库中广泛地使用了这个技巧,比如 size_t 在 VC++2010 的 crtdefs.h 文件中的定义如下所示:

#ifndef _SIZE_T_DEFINED
#ifdef  _WIN64
typedef unsigned __int64    size_t;
#else
typedef _W64 unsigned int   size_t;
#endif
#define _SIZE_T_DEFINED
#endif

2) 为自定义数据类型(结构体、共用体和枚举类型)定义简洁的类型名称
以结构体为例,下面我们定义一个名为 Point 的结构体:

struct Point
{
    double x;
    double y;
    double z;
};

在调用这个结构体时,我们必须像下面的代码这样来调用这个结构体:
struct Point oPoint1={100,100,0};
struct Point oPoint2;
在这里,结构体 struct Point 为新的数据类型,在定义变量的时候均要向上面的调用方法一样有保留字 struct,而不能像 int 和 double 那样直接使用 Point 来定义变量。现在,我们利用 typedef 定义这个结构体,如下面的代码所示:

typedef struct tagPoint
{
    double x;
    double y;
    double z;
} Point;

在上面的代码中,实际上完成了两个操作:
1、定义了一个新的结构类型,代码如下所示:

struct tagPoint
{
    double x;
    double y;
    double z;
} ;

其中,struct 关键字和 tagPoint 一起构成了这个结构类型,无论是否存在 typedef 关键字,这个结构都存在。

2、使用 typedef 为这个新的结构起了一个别名,叫 Point,即:
typedef struct tagPoint Point
因此,现在你就可以像 int 和 double 那样直接使用 Point 定义变量,如下面的代码所示:

Point oPoint1={1001000};
Point oPoint2;

为了加深对 typedef 的理解,我们再来看一个结构体例子,如下面的代码所示:

typedef struct tagNode
{
    char *pItem;
    pNode pNext;
} *pNode;

从表面上看,上面的示例代码与前面的定义方法相同,所以应该没有什么问题。但是编译器却报了一个错误,为什么呢?莫非 C 语言不允许在结构中包含指向它自己的指针?
其实问题并非在于 struct 定义的本身,大家应该都知道,C 语言是允许在结构中包含指向它自己的指针的,我们可以在建立链表等数据结构的实现上看到很多这类例子。那问题在哪里呢?其实,根本问题还是在于 typedef 的应用。
在上面的代码中,新结构建立的过程中遇到了 pNext 声明,其类型是 pNode。这里要特别注意的是,pNode 表示的是该结构体的新别名。于是问题出现了,在结构体类型本身还没有建立完成的时候,编译器根本就不认识 pNode,因为这个结构体类型的新别名还不存在,所以自然就会报错。因此,我们要做一些适当的调整,比如将结构体中的 pNext 声明修改成如下方式:

typedef struct tagNode
{
    char *pItem;
    struct tagNode *pNext;
} *pNode;

或者将 struct 与 typedef 分开定义,如下面的代码所示:

typedef struct tagNode *pNode;
struct tagNode
{
    char *pItem;
    pNode pNext;
};

在上面的代码中,我们同样使用 typedef 给一个还未完全声明的类型 tagNode 起了一个新别名。不过,虽然 C 语言编译器完全支持这种做法,但不推荐这样做。建议还是使用如下规范定义方法:

struct tagNode
{
    char *pItem;
    struct tagNode *pNext;
};
typedef struct tagNode *pNode;

3) 为数组定义简洁的类型名称
它的定义方法很简单,与为基本数据类型定义新的别名方法一样,示例代码如下所示:

typedef int INT_ARRAY_100[100];
INT_ARRAY_100 arr;

4) 为指针定义简洁的名称
对于指针,我们同样可以使用下面的方式来定义一个新的别名:
typedef char* PCHAR;
PCHAR pa;
对于上面这种简单的变量声明,使用 typedef 来定义一个新的别名或许会感觉意义不大,但在比较复杂的变量声明中,typedef 的优势马上就体现出来了,如下面的示例代码所示:
int (a[5])(int,char);
对于上面变量的声明,如果我们使用 typdef 来给它定义一个别名,这会非常有意义,如下面的代码所示:
// PFun是我们创建的一个类型别名
typedef int (PFun)(int,char);
// 使用定义的新类型来声明对象,等价于int
(a[5])(int,char);
PFun a[5];
小心使用 typedef 带来的陷阱
接下来看一个简单的 typedef 使用示例,如下面的代码所示:
typedef char
PCHAR;
int strcmp(const PCHAR,const PCHAR);
在上面的代码中,“const PCHAR” 是否相当于 “const char*” 呢?
答案是否定的,原因很简单,typedef 是用来定义一种类型的新别名的,它不同于宏,不是简单的字符串替换。因此,“const PCHAR”中的 const 给予了整个指针本身常量性,也就是形成了常量指针“charconst(一个指向char的常量指针)”。即它实际上相当于“charconst”,而不是“const char*(指向常量 char 的指针)”。当然,要想让 const PCHAR 相当于 const char* 也很容易,如下面的代码所示:
typedef const char* PCHAR;
int strcmp(PCHAR, PCHAR);
其实,无论什么时候,只要为指针声明 typedef,那么就应该在最终的 typedef 名称中加一个 const,以使得该指针本身是常量。
还需要特别注意的是,虽然 typedef 并不真正影响对象的存储特性,但在语法上它还是一个存储类的关键字,就像 auto、extern、static 和 register 等关键字一样。因此,像下面这种声明方式是不可行的:
typedef static int INT_STATIC;
不可行的原因是不能声明多个存储类关键字,由于 typedef 已经占据了存储类关键字的位置,因此,在 typedef 声明中就不能够再使用 static 或任何其他存储类关键字了。当然,编译器也会报错,如在 VC++2010 中的报错信息为“无法指定多个存储类”。
示例1

#include <stdio.h>
typedef char (*PTR_TO_ARR)[30];
typedef int (*PTR_TO_FUNC)(int, int);

int max(int a, int b)
{
    return a>b ? a : b;
}
char str[3][30] = 
{
    "http://c.biancheng.net",
    "C语言中文网",
    "C-Language"
};

int main()
{
    PTR_TO_ARR parr = str;
    PTR_TO_FUNC pfunc = max;
    int i;
   
    printf("max: %d\n", (*pfunc)(10, 20));
    for(i=0; i<3; i++){
        printf("str[%d]: %s\n", i, *(parr+i));
    }
    return 0;
}

示例2:

# include <stdio.h>

typedef struct Student
{
	int sid;
	char name[100];
	char sex;
}*PST; //PST等价于struct Student *

int main( void )
{
	struct Student st;
	PST ps = &st;
	ps->sid = 99;
	printf( "%d\n", ps->sid );
	
	return 0;
}

示例3

# include <stdio.h>

typedef struct Student
{
	int sid;
	char name[100];
	char sex;
}*PSTU, STU;//等价于STU代表struct Student, PSTU代表了struct Student *

int main( void )
{
	STU st;//struct Studtn st;
	PSTU ps = &st;//struct Student *ps = &st;
	ps->sid = 99;
	printf( "%d\n", ps->sid );
	
	return 0;
}

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef unsigned int u32;

//typedef和结构体结合使用
struct MyStruct
{
	int a;
	int b;
};

typedef struct MyStruct2
{
	int a;
	int b;
}TMP;

/* void, 无类型
1、函数参数为空,定义函数时,可以用void修饰:  int fun(void)
2、函数没有返回值:void fun(void);
3、不能定义void类型的普通变量: void a; //err,无法确定类型,不同类型分配空间不一样
4、可以定义void *变量: void *p; //ok, 32永远4字节,64永远8字节
5、数据类型本质:固定内存块大小别名
6、void *p万能指针,函数返回值,函数参数

*/

int main(void)
{
	u32 t; // unsigned int

	//定义结构体变量,一定要加上struct关键字
	struct MyStruct m1;
	//MyStruct m2; //err

	TMP m3;
	struct MyStruct2 m4;

	char buf[1024];
	strcpy(buf, "1111111111");
	void *p;
	
	printf("%c",buf[0]);
	

	printf("\n");
	system("pause");
	return 0;
}

控制流12个

if与else

if:条件语句
else :条件语句否定分支(与 if 连用)

switch、case和default

switch :用于开关语句  
case:开关语句分支  
default:开关语句中的“其他”分支

按照百分制考试分数输出等级
#include  "stdio.h"
main()
{
	int  grade;
	printf("input  grade=");
	scanf("%d",&grade);
	switch ((int)(grade/10))
	{ 
		case 10:  
		case  9:  printf("A\n"); break;
		case  8:  printf("B\n"); break;
		case  7:  printf("C\n"); break;
		case  6:  printf("D\n"); break;
		default:  printf("E\n");
	}    
}

for 、do和 while

C 语言中循环语句有三种:while 循环、do-while 循环、for 循环。
for:一种循环语句   
do :循环语句的循环体   
while :循环语句的循环条件

C:while

#include <stdio.h>         
void main ( )                   
{ 
	int sum=0,i=1;                  
	while (i<=100)                  
	{ 
		sum=sum+i; 
		i++;
	}                                 
	printf("sum=%d\n",sum);
}

C:do…while

#include <stdio.h>
void main( )
{
	int sum=0,i=1;
	do
	{
		sum=sum+i;
		i++;
	}while (i<=100);
	printf("sum=%d\n",sum);
}

C:for

#include <stdio.h>
void main( )
{
	int sum=0,i;
	for (i=1;i<=100;i++)
		sum=sum+i;  
	printf("sum=%d\n",sum);
}

goto

goto:无条件跳转语句  
一般来说,编码的水平与 goto 语句使用的次数成反比。

#include <stdio.h>
 
int main ()
{
   /* 局部变量定义 */
   int a = 10;

   /* do 循环执行 */
   LOOP:do
   {
      if( a == 15)
      {
         /* 跳过迭代 */
         a = a + 1;
         goto LOOP;
      }
      printf("a 的值: %d\n", a);
      a++;
     
   }while( a < 20 );
 
   return 0;
}

continue和break

continue:结束当前循环,开始下一轮循环   
break:跳出当前循环

return

return :子程序返回语句(可以带参数,也可不带参数)循环条件
return 用来终止一个函数并返回其后面跟着的值。

申明修饰符7个

void

void修饰函数返回值和参数
如果函数没有返回值,那么应该将其声明为void型
如果函数没有参数,应该声明其参数为void
void修饰函数返回值和参数仅为了表示无
不存在void变量
C语言没有定义void究竟是多大内存的别名
没有void的标尺,无法在内存中裁剪出void对应的变量
灰色地带 编译器产家自己定义void大小

static

第一个作用:修饰变量。
变量前加 static 使得函数成为静态变量。
第二个作用:修饰函数。
函数前加 static 使得函数成为静态函数。

//(1)变量不加 static 修饰

#include <stdio.h>

void test()
{
    int num = 0;
    num++;
    printf("%d ", num);
}
int main()
{
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        test();
    }
    return 0;
}

//(2)变量被 static 修饰

#include <stdio.h>

void test()
{
    static int num = 0;
    num++;
    printf("%d ", num);
}
int main()
{
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        test();
    }
    return 0;
}

const

声明只读变量
在C语言中const修饰的变量是只读的,其本质还是变量
const修饰的变量会在内存占用空间
本质上const只对编译器有用,在运行时无用
修饰一般变量:一般常量是指简单类型的只读变量。这种只读变量在定义时,修饰符 const 可以用在类 型说明符前,也可以用在类型说明符后。
修饰只读变量:定义 const 只读变量,具有不可变性。

#include<stdio.h>
int main(void)
{
    const int a;    //代表一个常整型数
    int const b;    //代表一个常整型数  

    const char *c;  // 是一个指向常整型数的指针
                    // (所指向的内存数据不能修改,
                    //  但是本身可以修改)
    char * const d; // 常指针(指针变量不能被修改,
                    //        但是它所指向的内存空间可以被修改)
    const char * const e;// 一个指向常量整型的常指针
                         // (指针和它所指向的内存空间,
                         //  均不可以修改)

    return 0;
}

auto

auto关键字声明一个变量为自动变量,是C语言中应用最广泛的一种类型,在函数内定义变量时,如果没有被声明为其他类型的变量都是自动变量,也就是说,省去类型说明符auto的都是自动变量。

#include <stdio.h>
#include <Windows.h>
int main()
{
	double value1 = 3.2, value2 = 3.5;  
	/*使用auto 定义一个变量,在C语言中可以不初始化,编译器会使用一个随机值
	值初始化变量val,但建议在写代码时进行初始化,为了说明与C++中的不同,这里
	不予初始化*/
	auto val;     
	val = value1 + value2; 
	printf("%d\n", val);
	system("pause");
	return 0;
}

register

register:指定为寄存器变量,建议编译器将变量存储到寄存器中使用,也可以修饰函数形参,建议编译器通过寄存器而不是堆栈传递参数

#include<stdio.h>
void main()
{
	register int i;
	int tmp = 0;
	for (i = 1; i <= 100; i++)
		tmp += i;
	printf("The sum is %d\n", tmp);
}

volatile

volatile:说明变量在程序执行中可被隐含地改变

volatile可理解为“编译器警告指示字”
volatile用于告诉编译器必须每次去内存中取变量值
volatile主要修饰被多个线程访问的变量
volatile也可以修饰可能被未知因数更改的变量

volatile:与const合称“cv特性”,指定变量的值有可能会被系统或其他进程/线程改变,强制编译器每次从内存中取得该变量的值

#include <stdio.h>
#include <stdlib.h>

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
const int* func()
{
	static int count=0;
	count++;
	return &count;
}
int main(int argc, char *argv[]) {
	volatile int i=0;
	volatile const int* p=func();
	printf("%d\n",*p);
	return 0;
}

extern

extern:声明变量是在其他文件正声明

// test.c
#include <stdio.h>
/*
extern "C"
{
    int add(int a, int b)
    {
        return a + b;
    }
}
*/

extern int g;
extern int get_min(int a, int b);
int main()
{  
    return 0;
}
// test2.c
int g = 100;
int get_min(int a, int b)
{
    return (a < b) ? a : b;
}

希望关注点赞评论,传递知识
想要关注我一起学习的请关注公众号:莫林的日常
想要和志同道合的伙伴一起学习的请加QQ群:515271405

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值