C语言中基础小问题详细介绍_C 语言

1、printf格式输出函数
如果格式控制说明项数多于输出表列个数,则会输出错误数据;
如果输出表列个数多于格式控制说明数,则多出数不被输出。
%md,m指的是输出字段的宽度。如果输出字段位数小于m,则左端以空格补齐,若大于m,则按照实际位数输出。
%-md,基本同上,只不过不同之处在于,空格在右端补齐
printf参数可以是常量,变量或表达式,VC++ 6.0中采用从右向左顺序求值,从左向右输出如

复制代码 代码如下:

int x = 5;
 printf("%4d%4d%4d", x, ++x, ++x);

输出的是7,7,6. 而不是5,6,7
注意,不同的编译器可能输出不同结果,直接用gcc编译结果为7,7,7
2、0-9数字转为字符
数字为m,则m+‘0'即为m的字符形式‘m'
3、小写字母变为大写字母
char c; c为小写字母,则c-'a'+'A'即为对应的大写字母
4、switch
如果找到匹配的case入口,则执行后面的语句,执行完语句之后,并不像if语句那样退出,如果没有遇到break语句,将逐条执行后面所有的case语句,不再进行条件判断。
case入口后面的语句可以是一句,也可以是多句,并且不需要大括号。
5、字符数组存储字符串
当char str[5]=new {"china"};时,程序会出问题,输出的时候会在china后带乱码,这是因为china字符串后还有一位'\0',因此应该给str数组多一位。即char str[6]=new {"china"};
且'\0'只表示字符串的结束,并不会输出。
scanf("%s",str);不能存入空格,因为认为空格代表字符串的结束。gets(str);可以在字符串中间加入空格。
puts(str);在输出字符串后自动加入换行
6、字符串操作函数
字符串拷贝函数:strcy(str1,str2); 将字符串str2拷贝到str1中。
字符串连接函数:strcat(str1,str2); 将str2连同'\0'一起连接到str1的最后一个字符(非'\0')后面,结果放在str1中。
字符串比较函数:strcmp(str1,str2); 比较str1和str2的大小,如果str1==str2,则返回0;如果str1>str2,则返回正整数;如果str1<str2,则返回负整数。
字符串长度函数:strlen(str); 返回字符串str的实际长度,不包括末尾的'\0'。
7、函数的参数和单向值传递
函数的参数分为实参和形参。形参出现在函数定义中,在整个函数体中使用,离开函数体则不能使用。实参出现在主调函数中,进入被调函数后,实参不能被使用。
形参只有被调用时才被编译系统分配内存单元,在调用结束时候,编译系统即刻释放所分配的内存单元,因此形参只在函数内部有效,函数调用结束返回主调函数后则不能再使用;
单向传值:只能把实参的值传递给形参,不能把形参的值反向传递给实参,叫做单向值传递。
因此,函数调用过程中,形参的值发生改变,实参的值不会改变
8、数组作为参数
数组名可以作为函数实参,这时候形参可以是数组或者指针。且形参是一维数组时候可以不指定长度。形参是二维数组时候,第一维大小可以省略,要指定第二维的大小。
9、变量的存储方式
(1)局部变量
局部变量在每次函数调用时,系统会在内存的动态存储区为他们重新分配内存单元,随着函数的频繁调用,某个变量的存储位置会随着程序的运行不断变化,所以未赋值的局部变量的值是不确定的。函数中的局部变量不能作为返回值,因为函数结束后,局部变量要被回收。
(2)static类型
静态变量在编译的时候被分配内存、赋初值,并且只会被赋初值一次。未赋初值的静态变量,系统自动赋初值0(或'0')。静态变量在内存静态存储区占用固定的内存单元。即使它所在的函数调用结束,也不会释放存储单元,其值也会继续保留,下次调用,会继续使用该值。静态变量分为静态局部变量和静态全局变量,静态全局变量就是定义在函数体外的静态变量,静态局部变量就是定义在函数体内的静态变量。
如下:

复制代码 代码如下:

#include<stdio.h>
void f()
{
    static int a=0; //编译时被赋初值,且整个过程只被赋初值一次
    ++a;
    printf("%-2d",a);
}
main()
{
    f();
    f();
    f();
}

以上程序的输出结果为1 2 3
因为对static变量赋初值是在编译时完成,而且只赋值一次,之后在调用函数不会执行赋初值操作,因此输出1 2 3 ;若去掉static关键字,那么结果就会变为1 1 1 ;由此看出,函数反复调用多次,局部变量每次都会被赋初值,而静态变量只是在第一次被调用的时候赋初值。
此处特变注意:java中是没有静态局部变量的,只会有针对类的静态全局变量。
(3)寄存器类型
定义形式: register 数据类型 变量名;寄存器类型局部变量的作用域、生存期与局部变量相同。
寄存器的个数有限,寄存器的存储数据位数有限,所以寄存器类型的变量不能太多,而且有整型变量和字符型变量才能被定义为寄存器类型的局部变量。现在的优化系统可以自动的判断把相关变量存到寄存器中。
(4)外部变量
10、编译预处理
#include<文件名>和#include"文件名"的区别是:使用尖括号时,编译预处理程序只在系统指定的文件夹中寻找;而使用双引号,编译预处理程序首先在当前文件所在的文件夹中寻找,如果找不到,则在系统指定的文件夹中再寻找。
11、&和*
优先级都属于第二级,从右向左运算
12、*与++、--运算符
都属于第二级,从右向左计算
*p++  等价于  *(p++)
*++p  等价于  *(++p)
13、[  ]和*
[  ]优先级高于*
13、二维数组的行地址和列地址
int a[2][2]={1,2,3,4};
则a为首地址,第一行首地址;*a和a[0]都是第一行第一个元素的地址
a+1为第二行行地址
*(a+1)为第二行第一个元素地址,a[1]也为第二行第一个元素地址
14、指向数组的指针变量(数组指针)
int *(p) [4];表示一个指向含有4个int元素的数组的指针。
(1)p指向一维数组的首行地址

复制代码 代码如下:

main()
{
    int a[2]={1,2};
    int (*p)[2];
    p=&a;//p是指向数组的指针,即行指针,因此要用&a给其赋值,&a为数组地址
    printf("%d\n",**p);//取第一个元素,其中p为行地址,*p为元素地址,**p为元素值
    printf("%d\n",*(*p+1));//取第二个元素
    //也可以如下取值
    printf("%d\n",(*p)[0]);//(*p)可以取代a
    printf("%d\n",(*p)[1]);
}

(2)p指向二维数组的首行地址

复制代码 代码如下:

main()
{
    int a[2][2]={1,2,3,4};
    int (*p)[2];
    p=a;//p指向二维数组的首行地址
    printf("%d\n",**p);//*p是元素的地址,**p则为元素内容
    printf("%d\n",*(*(p+1)+1));
}

15、指针数组
int *p[4];表示一个数组中含有4个int型指针。
char *p[4];表示一个数组中含有4个char型数组,或则4个字符串
16、二维数组中的各个地址
int a[2][3];
则a为首行地址,*a为首行第一个元素地址,**a为首行第一个元素的值
a+1为第二行地址,*(a+1)为第二行第一个元素的地址,**(a+1)为第二行第一个元素的值
*(a+1)与a[1]等价:都代表第二行第一个元素的地址
例子:

复制代码 代码如下:

main()
{
    int a[2][2]={1,2,3,4};
    printf("a=%d\n",a);
    printf("*a=%d\n",*a);
    printf("**a=%d\n",**a);
    printf("*a+1=%d\n",*a+1);
    printf("a+1=%d\n",a+1);
    printf("a[1]=%d\n",a[1]);
    printf("a[1]+1=%d\n",a[1]+1);
    printf("*a[1]=%d\n",*a[1]);
}

17、字符指针变量在接受输入字符串时,必须先开辟存储空间
char *cp;
scanf("%s",cp);
以上是错误的。
可以改为:
char cp[20];
scanf("%s",cp);
或者
char *cp,str[20];
cp=str;
scanf("%s",cp);
总之,一定要先开辟空间,再接受字符串
18、c和c++中的返回值不能是数组,java返回值可以是数组
19、指针函数和函数指针
指针函数:int * function();
函数指针:

复制代码 代码如下:

int (*p) ();
int max(int a,int b);
p=max;
int a=(*p)(2,3);

20、关于变量的生命周期
函数中定义的局部变量是不能作为返回值的,因为函数结束后,局部变量就被回收了。
21、结构体
结构体中可以嵌套结构体,但不能是其本身。且成员结构体的定义必须在主结构体之前。
22、malloc
malloc函数位于stdlib.h中,函数原型为void * malloc(unsigned size);
eg: struct student *p=(struct student *)malloc(sizeof(struct student));
因为malloc返回的是一个void类型的指针,所以要强制转换。
23、free
该函数原型为
void  free(void * ptr)
释放有指针ptr指向的动态分配的内存空间。为保证动态存储区的有效利用,当某个存储空间不再使用时,就应该及时释放它。

24、结构体和共用体
(1)结构体
结构体可以作为函数的参数和返回值。
结构体只有在初始化的时候才能直接用大括号{}形式赋值;当先声明,后赋值时候,就只能单个元素赋值,不能再用大括号形式了。这个跟数组的赋值类似。举例如下

复制代码 代码如下:

struct student
{
    int bh;
    char *name;
};
struct student stu={1,'typ'};//是正确的

但是下面的是错误的

复制代码 代码如下:

struct student stu;
stu={1,"typ"};//是错误的

此时这能stu.bh=1;stu.name="typ"
(2)共用体
共用体不能作为函数的参数和返回值
共用体不能同时存放,每一时刻只能存放一个成员,以最后一次存放的成员为有效成员。共用体的大小是最大元素所占用的大小;
共用体可以出现在结构体类型中,反之,结构体也可以出现在共用体的类型中
25、枚举类型

复制代码 代码如下:

enum color {red,green,blue};
enum color c=red;
int i=red;//值为0

26、类型标识符的重定义
c语言中用关键字typedef来声明新的类型名
typedef int INTEGER;
INTEGER x,y;
等价于
int x , y;
又比如结构体定义:

复制代码 代码如下:

typedef struct
{
    int num;
    char name[10];
    float score;
}student;
student  stu1, stu2, *s;

另外,typedef只是进行类型重定义,只是为该类型命名一个别名,并不产生新的数据类型
27、位运算
包括(与、或、异或、取反)。
其中,位运算符进行运算时,数都是以补码形式参加运算,且符号位参与运算。
异或:相同为0,不同为1
a^a=0;a^0=a;a^~a=1;
此处可以用异或来实现两数的交换
a=a^b;
b=b^a;
a=a^b;
这样避免引入临时变量
28、移位运算
(1)a<<b,表示a的二进制值左移b位
(2)a>>b,表示a的二进制值右移b位
移位运算具体实现有3种形式:
(1)循环移位:移入的位等于移出的位
(2)逻辑移位:移出的位丢失,移入的位取0
(3)算术移位:移出的位丢失,左移入的位取0,右移入的位取符号位,符号位保持不变
C语言的移位运算与具体的C编译系统有关,如VC++6.0采用的是算术移位
注意:移位操作并不会改变原操作数的值。例如a>>2运算后,a的值保持不变,除非通过赋值a=a>>2来改变a的值。

29、文件
(1)C语言中文件是字节流文件.
(2)C中为用户定义的文件类型是FILE,FILE文件类型是结构体类型,FILE结构是用关键字typedef定义出的一种结构。

复制代码 代码如下:

struct  _iobuf
{
char * _ptr;
int _cnt;
char *base;
int _flag;
int _file;
.........
};
typedef struct  _iobuf  FILE;

(3)文件打开与关闭
文件指针 = fopen("文件路径\\文件名", "文件操作方式");
操作方式分为r,w,a,r+,w+,a+
如果fopen打开失败,则返回NULL

如果缓冲区未满512B,那么不会写到磁盘中,万一程序异常终止,则缓冲区中数据丢失,导致文件不完整。只有对打开文件执行关闭操作时,才能强制把缓冲区中不足512B的数据写到磁盘文件中,保证文件的完整性。fclose函数用来关闭文件
fclose(文件指针);
返回值是一个整数值,若为0,表示正常关闭,否则表示无法正常关闭文件。
(4)文件的输入和输出
读写一个字符:char fgetc(文件指针);EOF fputc(字符,文件指针)
读写一个字符串:fgets(字符串s,读入字符个数n,文件指针)--->在中途遇到\n或者EOF停止,读n-1个字符,在末尾加'\0';fputs(字符串,文件指针)--->字符串的结束标记不会写入文件
格式化读写:fscanf(fp, "%d%s", &i, s)--->从文件中读取数据保存到变量;fprintf(fp, "%d%c", j, c)--->按指定格式向文件写入数据
成块读写:fread(buffer,size,count,fp)和fwrite(buffer,size,count,fp)
buffer是一个指针,fread()中表示存放“输入数据”的变量首地址,fwrite()中表示存放“输出数据”的变量首地址
size表示数据块的字节数
count表示数据块个数
fp文件指针
返回值都是count值
(4)其他文件操作的函数
feof(fp)判断文件的末尾标志,到达末尾返回1,否则返回0
rewind(fp)用于定位,是文件的位置指针返回文件开头。
fseek(fp, offset, base)用来控制文件内部位置指针移动。base是位置移动的基准点。offset是偏移量
ftell(fp)用于获取位置指针的位置,相对于文件开头。

时间: 2024-08-22 14:10:33

C语言中基础小问题详细介绍_C 语言的相关文章

在C语言中转换时间的基本方法介绍_C 语言

C语言mktime()函数:将时间转换成经过的秒数头文件: #include <time.h> 定义函数: time_t mktime(strcut tm * timeptr); 函数说明:mktime()用来将参数timeptr 所指的tm 结构数据转换成从公元1970 年1 月1 日0 时0 分0 秒算起至今的UTC 时间所经过的秒数. 返回值:返回经过的秒数. 范例:用time()取得时间 (秒数), 利用localtime() 转换成struct tm 再利用mktine()将stru

C++开发:为什么多线程读写shared_ptr要加锁的详细介绍_C 语言

我在<Linux 多线程服务端编程:使用 muduo C++ 网络库>第 1.9 节"再论 shared_ptr 的线程安全"中写道: (shared_ptr)的引用计数本身是安全且无锁的,但对象的读写则不是,因为 shared_ptr 有两个数据成员,读写操作不能原子化.根据文档(http://www.boost.org/doc/libs/release/libs/smart_ptr/shared_ptr.htm#ThreadSafety), shared_ptr 的线程

C语言 位段的详细介绍_C 语言

C语言中的位段       位段(bit-field)是以位为单位来定义结构体(或联合体)中的成员变量所占的空间.含有位段的结构体(联合体)称为位段结构.采用位段结构既能够节省空间,又方便于操作.      位段的定义格式为:      type  [var]: digits     其中type只能为int,unsigned int,signed int三种类型(int型能不能表示负数视编译器而定,比如VC中int就默认是signed int,能够表示负数).位段名称var是可选参数,即可以省

C语言中static的作用及C语言中使用静态函数有何好处_C 语言

想了解Java中static关键字的作用和用法详细介绍,请点击此处了解详情. 在C语言中,static的字面意思很容易把我们导入歧途,其实它的作用有三条,分别是: 一是隐藏功能,对于static修饰的函数和全局变量而言 二是保持持久性功能,对于static修饰的局部变量而言. 三是因为存放在静态区,全局和局部的static修饰的变量,都默认初始化为0 下面我逐一给大家介绍: (1)先来介绍它的第一条也是最重要的一条:隐藏. 当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有

简单讲解C语言中宏的定义与使用_C 语言

宏定义是预编译功能的一种, 预编译又称为预处理, 是为编译做的预备工作的阶段.处理#开头的指令, 比如拷贝 #include 包含的文件代码,#define宏定义的替换,条件编译等. 使用宏定义的好处:使用宏定义的好处:可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改.例如 π 这个常量,我们有时候会在程序的多个地方使用,如果每次使用都重新定义,一来比较麻烦,二来容易出错,所以我们可以把 π 做成宏定义来使用.   语法说明: (1)宏名一般用大写 (2)使用宏可提高程序的通用性

Go语言中的复合类型详细介绍_Golang

golang复合类型包括:结构体.数组.切片.Maps. 1.数组 数组 golang中的数组与C语言中的数组差异很大,倒更类似Pascal中的数组. (Slice,下个话题,有些像C语言中的数组) 复制代码 代码如下: var ar [3]int 声明ar为一个拥有三个整型数的数组,所有元素初始化为0. 大小是类型的一个组成部分. 内置的函数len可以用于获取数组大小: 复制代码 代码如下: len(ar) = 3 数组是值类型 golang中的数组是值,而非C语言中的隐式指针.你可以获得数组

c语言中数组名a和&amp;amp;a详细介绍_C 语言

最近又把学习c语言提上日程上来了~~~先把我打算看的书都写下来吧,<C语言深度剖析>,<c和指针>系类,<c语言陷阱和缺陷> 先说说a和&a的区别(有三点,三个方向):1.是a和&a的本质,都是什么类型的.2.从2维数组的角度看.3.从指针运算的角度看. 声明:虽然数组名不是指针,但是用的很像指针,我们暂且把它叫做一个指针吧. 第一个问题:int a[10];  a ,&a和&a[0] 都是分别是什么?先说明a ,&a和&

关于C++内存中字节对齐问题的详细介绍_C 语言

一.什么是字节对齐计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐. 二.对齐的作用和原因:1.平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的:某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常.各个硬件平台对存储空间的处理上有很大的不同.一些平台对某些特定类型

C++ Qt属性系统详细介绍_C 语言

C++ Qt属性系统详细介绍 Qt提供了一个绝妙的属性系统.跟那些由编译器提供的属性差不多.然而,作为一个独立于编译器和平台的库,Qt不依赖于非标准的编译特性,比如__property 或[property].Qt可以在任何平台上的标准编译器下编译.Qt属性系统基于元数据对象系统--就是那个提供了对象内置信号和槽通讯机制的家伙. 声明属性需要什么 要声明一个属性,需在继承自QObject的类中使用Q_PROPERTY()宏. Q_PROPERTY(type name READ getFuncti