C

原创 2012年03月24日 19:35:13

写一个C程序first.c

1,预处理 gcc -E first.c -o first.i -->first.

2,编译   gcc -c first.i-->first.o

3,连接         gcc first.o-o first -->first

gccfirst.c

 

sizeof()括号内的运算式不进行运算,只是推断一下大小

 

优先级:

1,()最高 =最低

2,单目运算符比双目运算符高

 

赋值运算符,和单目运算符是右结合的

其他的基本为左结合

 

与或非

1 && X = X

1 || X = 1

异或

1 ^ X = -X

0 ^ X = X

按位取反:

先加1,符号反转

 

两个数参与运算

1,小范围的数转成大范围的数

2,最小的计算单位是int

 

switch语句:

case后面一定要为常量表达式,而且不能重复

 

函数:

void fun() {}

当传参数时,可以随意传入参数,只不过没意义

如果不想函数里面传递参数,可以规定:void fun(void){}

调用函数之前,函数必须先声明或先定义,否则,C处理成隐式声明,返回int

尽量不要使用隐式声明

隐式声明, int函数名(根据实参推)

递归

1,退出

2,递归调用向已知靠近

3,效率低,内存消耗大

4,适合解决特别复杂的问题(这个复杂问题可以简化成若干简单问题)

 

全局变量如果没有初始化,会自动初始化为0,作用域是整个程序,可以在任何地方访问,前面没有默认的auto修师符,也不能加auto

 

 

指针:

int* p1, p2;是定义了一个int指针和一个int变量

 

注意:

a[i] ==*(a+i)

*(a+i) ==*(i+a)

*(i+a) ==i[a]

所以a[i] ==i[a]

指针和数组区别:

1,sizeof结果不同

2,数组名不可更改(数组a[],指针p++p可以,而++a错误)

其他数组和指针一样,可将数组名当指针用

数组名本身:

本身是常量,不可改变,sizeof可以获取整个这片内存的长度

自定义指针指向一片数组区域:

指针是变量,可以改变,sizeof结果为4

char*fa() {

//函数中返回字符串常量的地址是可以的(在代码区)

return"abcdef";        

}

 

char*fb() {

//static是在全局区,所以返回地址是可以的

static int x = 10;

return &x;        

}

 

int* fc(){

//这是不可以的

int x = 10;

return &x;        

}

 

char*fd() {

//这也不可以(在栈区分配的局部变量)

char str[] = "abcdef";

return str;

}

 

进程内存空间:

代码区 : 程序代码,只读区,不可改

全局区 : 全局变量

堆 : 程序员自己申请

栈 : 局部变量,函数形参...

main函数:

int main(void)

int main()

int main(int argc, char* argv[])

int maim(int argc, char** argv)

int main(int argc, char** argv, char** env)

#define

宏函数:#define 标识符(...) ...

注意:标识符和(之间不能有空格

宏函数:

1,所有参数应用()将其包含,否则使用表达式时可能错误

2,在调用宏函数时,不要使用++,--,否则不能保证结果正确

 

优点:

1,程序可能会稍微快一点

2,宏更"通用"

3,宏函数中的参数不检查类型

缺点:

1,编译后的代码通常会变大

2,宏参数没有类型检查

3,无法用一个指针指向宏

4,宏可能会不止一次地计算它的参数(n= MAX(i++, j);)

5,可读性差,错误很难查出

"#"运算符

只能出现在宏函数中,作用是将参数字符串化

#define PRINT_INT() printf(#n

"##"运算符

将两个标记连成一个标记,一般情况下,两个标记中的一个是参数

 

预定义宏

__LINE__ 源程序行号

__FILE__ 源程序文件名

__DATE__ 现在日期

__TIME__ 现在时间

__STDC__ 是否支持标准C,支持为1,不支持为0

 

注意:

在全局变量前面加上static是为了限制其范围,只能在本文件内访问此全局变量

在函数前面加static也是为了限制其访问权限,只能在本文件内访问此函数

 

给类型起别名的方法:

1,先用这种类型定义一个变量

2,在最前面加typedef

那个变量名就是类型的别名

Example: typedef int I10[10];

而不是 typedef int[10] I10;

预处理器 将///* */ 去掉

编译器将#.... 去掉

 

全局变量

extern 类型 变量名

静态全局变量

限制变量的访问

静态全局函数

限制函数的调用

 

结构体

p-> 相当于 (*p).

 

对齐,补齐

由于内存分配会将结构中的变量分配到内存的边界上,以方便访问。

所以每个成员放的位置是从本身长度的倍数位开始放。

但本身长度超过4时,以4计。此称为对齐。

char   1倍

short  2倍

int    4倍

double4倍                

整个结构变量的长度要保持内部最长成员(超过4以4计)的倍数。

如果不够,则补齐。

 

位段

本质是结构

struct Switch {

int s1 : 1    //1代表一个二进制位

int s2 : 1

int s3 : 1

int s4 : 1

int s5 : 1

};

 

函数指针

函数名其实是一个常量指针

为什么用函数指针

函数指针的应用比较广泛,函数指针是变量,

所以变量能出现的地方,函数指针就可以出现

比如,可以用数组保存很多函数,

可以把函数作为另外一个函数的参数进行传递,用一个函数返回一个函数

 

静态分配 :编译期间可以确定需要分配内存的大小

int x; : 在栈分配

动态分配 :编译期间不能确定所需要分配内存的大小,

只有程序运行时才能确定分配空间的大小.

   在堆空间中分配,堆空间内存分配比较自由,

                  分配空间和释放空间由程序员自己确定,堆区也叫自由区

malloc:

分配多少空间后在之后的一个空间位置设置一个标记,当free时从开始位置释放空间,直到遇到此标记时结束,因此如果越界访问可能会破坏此标记,引发内存错误,也可能产生段错误(超过页面大小)

malloc和calloc的功能相同,可以通用,唯一的区别就是calloc会将分配好的内存清零

mallco和calloc分配空间的首地址一定要保存下来,否则在free时会出现内存错误

realloc :函数调整分配后的大小

1,当扩展内存时,不会对增加的内存初始化

2,失败时返回空指针,原内存中的数据不会改变

3,第一个参数是空指针时,如同调用malloc

4,如果以0作为第二个参数,会释放原内存块

5,小心,realloc可能会将内存块移到别的地方去。

 

free:

1,参数需要释放空间的首地址,确定堆空间的结束标记没有被破坏

2,两次释放同一片空间会造成内存错误(double free)

3,当free掉一片空间后,应该立即把指向该空间的指针置零

4,谁申请的空间谁释放,否则可能造成悬空指针

 

数组指针

int n[10];

数组a的值是第一个元素的地址(下标0)的地址

a的类型int[10]实质上是int* const类型

所以*a 等同 a[0]

如果&a,则取到整个数组的首地址

与a[0]地址相同,但意义不同,类型为int (*pa)[10] = &a

inta[3][4],a是一个数组,数组里有3个元素,每个元素是int[4]类型的数组

a是第一个元素的地址,a的类型就是int[3][4],int(*)[4]

int(*pa)[4] = a;

 

stdout 和stderr的区别

1,stdout带缓冲区,stderr不带缓冲区

2,stdout可以重定向,stderr不能重定向

3,什么时候stdout缓冲区会清空:

1)缓冲区清空时,缓冲区的内容会送到显示器

2)当输出换行时会清空

3)当等待用户输入时会清空

4)当调用fflush函数时清空

5)当程序运行结束时清空

6)当缓冲区满时清空

 

sprintf:

可以将任何数据转成指定格式的字符串

 

va_list:处理步骤固定,如下

va_listva;                //1,声明一个va_list类型的变量,用来保存所有可变长参数

va_start(va,n);        //2,将所有的参数保存到va_list里

va_arg(va,i);        //3,从va_list中逐个取出参数进行处理

va_end(va);                //4,释放va_list

JSTL <C:if></C:if> 和<C:ForEach></C:ForEach> 入门级~

JSTL
  • Abubu123
  • Abubu123
  • 2016年06月16日 14:33
  • 10147

c中的# #@ 和##

c/c++的预处理定义:一、Stringizing Operator (#) 在c和c++中数字标志符#被赋予了新的意义,即字符串化操作符。其作用是:将宏定义中的传入参数名转换成用一对双引号括起来参数...
  • Augusdi
  • Augusdi
  • 2014年06月09日 13:49
  • 2735

关于C语言中类似"a<b<c"条件的值

想起上学期在百度上回答的一个C语言问题,如下 ———————————————————————————————————— #include "stdio.h" main() { int a=1,b=2...
  • octobershiner
  • octobershiner
  • 2011年08月03日 13:36
  • 7849

C语言选择排序详解及其实现

选择排序(Selection sort)是一种简单直观的排序算法。这次我们依然将其分为有序组与无序组。 (我将冒泡排序的链接放到这里,有兴趣的可以看看,冒泡排序:http://blog.csdn.ne...
  • LLZK_
  • LLZK_
  • 2016年06月10日 21:48
  • 25338

C语言正则表达式regex

From: http://hi.baidu.com/david_jlu/blog/item/87ada1dbb9af6a60d0164eda.html 正则表达式在linux下应用非常广泛,经常使用...
  • JoeBlackzqq
  • JoeBlackzqq
  • 2012年01月26日 18:47
  • 4488

数组去重(c语言实现)

起因 在九度练习acm的时候,有道题我认为应该先进行数组去重操作,由于工作中我大部分都是用php写代码,php中数组去重只要一个array_diff()函数即可实现,但是到C语言中,我就没有现成的a...
  • zinss26914
  • zinss26914
  • 2012年10月16日 00:03
  • 16436

Linux下C语言执行MySQL语句

执行SQL语句的增、删、改、查的主要API函数为: int mysql_query(MYSQL *connection, const char *query); 函数接收参数连接句柄和字符串形式的有...
  • shuangde800
  • shuangde800
  • 2013年12月27日 23:14
  • 14086

读经典《C程序设计语言》(The C Programming Language)

作为软工专业的学生,大三下,我重新开始学习C语言,为什么呢?因为我发现在大学生涯里,我花了很多时间去刷GPA,花了很多时间去做了很多无谓的事情,以至于马上就面临找实习、找工作。自己甚至连一门语言都没有...
  • stc_XC
  • stc_XC
  • 2017年05月30日 22:54
  • 923

循环队列及C语言实现<一>

循环队列是为了充分利用内存,进行数据操作的一种基本算法。具体实现方式可划分为:链式队列和静态队列,这里所谓的静态是指在一片连续的内存区域进行数据操作。本文只讲述静态队列,也是最简单的实现方式,静态队列...
  • JAZZSOLDIER
  • JAZZSOLDIER
  • 2016年09月21日 22:34
  • 3848

C - C

C - CTime Limit:1000MS Memory Limit:30000KB 64bit IO Format:%lld & %llu SubmitStatus Descr...
  • DTL66
  • DTL66
  • 2016年07月23日 14:19
  • 107
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C
举报原因:
原因补充:

(最多只允许输入30个字)